1.权限管理
2.权限模型
主体(账号、密码)
资源(资源名称、访问地址)
权限(权限名称、资源id)
角色(角色名称)
角色和权限关系(角色id、权限id)
主体和角色关系(主体id、角色id)
注:一般资源和权限是放在同一张表里面得,什么样得权限能访问什么资源(一般也就是请求的url)
3.授权流程
1.SecurityManager
SecurityManager即安全管理器,对全部的subject进行安全管理(也就是任何在applicationcontext-shiro中配置的bean,都要通过它的认证),它是shiro的核心,负责对所有的subject进行安全管理。通过SecurityManager可以完成subject的认证、授权等,实质上SecurityManager是通过Authenticator进行认证,通过Authorizer进行授权,通过SessionManager进行会话管理等
<!-- securityManager安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="customRealm" />
<!-- 注入缓存管理器 -->
<property name="cacheManager" ref="cacheManager"/>
<!-- 注入session管理器 -->
<property name="sessionManager" ref="sessionManager" />
<!-- 记住我 -->
<!-- <property name="rememberMeManager" ref="rememberMeManager"/> -->
</bean>
2.realm
Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息。
更确切的说是从数据库中取出信息和从登陆会话中取出的信息进行认证和授权。
3.authenticator和authorizer
前者是认证器,对用户身份进行认证
后者是授权器,判断用户是否有对此功能的操作权限。
4.subject
Subject即主体,外部应用与subject进行交互,subject记录了当前操作用户,将用户的概念理解为当前操作的主体
,可能是一个通过浏览器请求的用户,也可能是一个运行的程序。Subject在shiro中是一个接口,接口中定义了很多认证授相关的方法,
外部程序通过subject进行认证授,而subject是通过SecurityManager安全管理器进行认证授权
理解了之后接下来就是授权流程:
1、对subject进行授权,调用方法isPermitted("permission串")
2、SecurityManager执行授权,通过ModularRealmAuthorizer执行授权
3、ModularRealmAuthorizer执行realm(自定义的CustomRealm)从数据库查询权限数据
调用realm的授权方法:doGetAuthorizationInfo
4、realm从数据库查询权限数据,返回ModularRealmAuthorizer
5、ModularRealmAuthorizer调用PermissionResolver进行权限串比对
6、如果比对后,isPermitted中"permission串"在realm查询到权限数据中,说明用户访问permission串有权限,
否则 没有权限,抛出异常。
// 用于认证,
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
// token是用户输入的
// 第一步从token中取出身份信息
String userCode = (String) token.getPrincipal();
// 第二步:根据用户输入的userCode从数据库查询
SysUser sysUser=null;
try {
sysUser=sysService.findSysUserByUserCode(userCode);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
//
// 如果查询不到返回null
//数据库中用户账号是zhangsansan
if(sysUser==null){//
return null;
}
//盐
String salt=sysUser.getSalt();
// 模拟从数据库查询到密码
String password = sysUser.getPassword();
// 如果查询到返回认证信息AuthenticationInfo
ActiveUser activeUser=new ActiveUser();
activeUser.setUserid(sysUser.getId());
activeUser.setUsercode(sysUser.getUsercode());
activeUser.setUsername(sysUser.getUsername());
//..
//根据用户id取出菜单
//通过sevice取出菜单
List<SysPermission> menus=null;
try {
menus=sysService.findMenuListByUserId(sysUser.getId());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//将用户菜单设置到activeuser
activeUser.setMenus(menus);
//将activeuser设置到SimpleAuthenticationInfo
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
activeUser, password,ByteSource.Util.bytes(salt), this.getName());
return simpleAuthenticationInfo;
}
// 用于授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
// TODO Auto-generated method stub
//从principals获取主身份信息
//将getprimaryprinciple方法返回值转换为真实的身份类型
ActiveUser activeUser=(ActiveUser)principals.getPrimaryPrincipal();
List<SysPermission> permissionList=null;
//根据身份信息获取权限信息
//连接数据库...
//模拟从数据库获取到数据
try {
permissionList=sysService.findPermissionListByUserId(activeUser.getUserid());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//单独定义一个集合对象
List<String> permissions=new ArrayList<String>();
if(permissionList!=null){
for(SysPermission sysPermission:permissionList)
{
//将数据库中的权限标识符号放入集合
permissions.add(sysPermission.getPercode());
}
}
//查到权限数据,返回授权信息(要包括 上边的permissions)
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//将上边查询到授权信息填充到simpleAuthorizationInfo对象中
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}