您当前的位置: 首页 >  数据库

Charge8

暂无认证

  • 4浏览

    0关注

    430博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Shiro 从数据库中初始化授权

Charge8 发布时间:2019-04-26 16:39:49 ,浏览量:4

根据前面的了解,这次把基于权限的授权通过从数据库中初始化授权实现。

1、分析一下 Shiro 过滤链
    
    
    	  
		
		 
		  
		
		  
		 
		  
		  
		
			
				
				/login = anon
				/logout = logout
				/admin/userlist = perms[userlist]
				/admin/addUser = perms[addUser]
				/admin/** = authc    
				/**= anon  
			
		 
	

    点击 filterChainDefinitions 属性, 进去查看源码

1)可以看到它是 ShiroFilterFactoryBean 的一个属性:

    

2)经过一系列初始化后,它调用了 setFilterChainDefinitionMap 这个方法,点开这个方法:

     

3)通过 debug的方式 可以看到在初始化时, filterChainDefinitionMap是一个LinkedHashMap,其内容就是我们在配置文件中配置的内容

   

所以我们可以配置一个单独的 bean filterChainDefinitionMap 作为ShiroFilterFactoryBean的属性。 然后通过实例工厂的方式来产生Map通过实例工厂注册的Map实例,然后我们需要去新建并配置一个Bean

2、分析后,修改spring.xml 

数据库:

        将 授权信息 放到 数据库中(事前约束规定,perms使用p:  roles 使用 r: )

       

其他几个表和之前一样,没变化。

用户admin, 只拥有角色 admin 和 user 与访问  /admin/userlist 的权限资源,如果 pid 为3和4,则两者都可访问。

注意:

       1)t_permission 的 数据顺序:从上到下,拦截范围必须是从小到大的

        2)用户表 model 实现 序列化:

    

1) 配置bean

    
    
    	  
		
		 
		  
		
		  
		 
		  
		
		  
		
    

	
	
	

2)创建这个bean

import cn.jq.ssm.dao.PermissionMapper;
import cn.jq.ssm.model.Permission;

public class FilterChainDefinitionMapFactory {

	@Autowired
	private PermissionMapper permissionMapper;
	
	public Map getFilterChainDefinitionMap(){
		//从数据库中获取数据
		List permissions = permissionMapper.getAllPermissions();
		
		LinkedHashMap permsMap = new LinkedHashMap();
		
		for (Permission permission : permissions) {
			if(permission.getPname().contains("p:")) {
				//构造perms[userlist]
				String perms = permission.getPname().replace("p:", ""); //删除前缀
				permsMap.put(permission.getUrl(), "perms["+ perms +"]");
			}else {
				permsMap.put(permission.getUrl(), permission.getPname());
			}
		}
		
		return permsMap;
	}
}

PermissionMapper 方法:

	
		select
			p.id,p.pname,p.url
		from 
			 t_permission p
	

3)自定义 ShiroRealm 类, 对于约束 p: 也做相应处理

public class ShiroRealm extends AuthorizingRealm{
	/*
	 * public class ShiroRealm extends AuthenticatingRealm{
	 */
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private RoleMapper RoleMapper;
	@Autowired
	private PermissionMapper permissionMapper;
	/**
	 *  在 shiro 中专门做登录验证的方法
	 * @param token
	 * @return
	 * @throws AuthenticationException
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken token2 = (UsernamePasswordToken) token;
		String username = token2.getUsername();
		User user = userMapper.getUserByUsername(username);
		if(user == null) {
			throw new UnknownAccountException("用户名或密码有误!");
		}
		if(user.getStatus() == 0) {
			throw new UnknownAccountException("用户名已被禁用,请联系系统管理员!");
		}
		
		/**
		 * principals: 可以使用户名,或d登录用户的对象
		 * hashedCredentials: 从数据库中获取的密码
		 * credentialsSalt:密码加密的盐值
		 * RealmName:  类名(ShiroRealm)
		 */
		ByteSource credentialsSalt = ByteSource.Util.bytes("JQSalt");
		AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPazzword(), credentialsSalt, getName());
		return info;
	}
	
	/**
	 * 在 shiro 中专门做授权认证的方法
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {		
		
		//1 从参数 principals 中获取当前登录成功后的用户信息
		User user = principals.oneByType(User.class);
		//2 根据第一步中的用户信息,获取角色信息(若用户信息包含角色/权限信息,直接取出,若没有,从数据库中获取)
		Set roles = RoleMapper.getRolesByUserid(user.getId());
		// 通过用户关联的role信息,获取角色关联的 permisssion信息
		Set permissions = permissionMapper.getPermissionsByUserid(user.getId());
		
		Set newPermissions = new HashSet();
		for (String permission : permissions) {
			if(permission.contains("p:")) {
				//删除约定前缀
				newPermissions.add(permission.replaceAll("p:", ""));
			}else {
				newPermissions.add(permission);
			}
		}
		
		//3 把获取到的登录用户关联的角色和权限资源信息注入到返回的SimpleAuthorizationInfo对象中
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addRoles(roles);
		info.addStringPermissions(newPermissions);
		return info;
	}

}
3、登录访问项目:

        结果和分析一致

    参考文章: spring工厂方式创建bean实例   

end ~

 

 

关注
打赏
1661954522
查看更多评论
立即登录/注册

微信扫码登录

0.4538s