1.权限资源标识符号为
资源:操作:实例
即user:create:01
可以用*代替表示全部
2.认识用户、角色、权限、资源关系
zhang=123,role1,role2
li=456,role3
即用户表和角色表多对多,一个用户多个角色
role1=user:create,user:delete
role2=user:create,user:update
role3=user:delete
即角色和权限多对多,一个角色多个权限
3.认证授权流程--自定义realm
首先 由ShiroFilterFactoryBean中定义的formAuthenticationFilter(表单认证过滤器)进行表单提交过来的信息进行处理,并返回token给realm
<!-- 安全认证过滤器 -->
<bean id="shiroFilter" class="com.dq.shiro.security.MyShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
<property name="loginUrl" value="${adminPath}/login" />
<!-- loginUrl认证成功后跑的地址-->
<property name="successUrl" value="${adminPath}?login" />
<property name="filters">
<map>
<entry key="cas" value-ref="casFilter"/>
<!-- 表单校验过滤器 ref-->
<entry key="authc" value-ref="formAuthenticationFilter"/>
</map>
</property>
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
表单认证过滤器核心代码
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
String username = getUsername(request);
String password = getPassword(request);
if (password==null){
password = "";
}
boolean rememberMe = isRememberMe(request);
String host = com.dq.base.web.utils.WebUtils.getIpAddr((HttpServletRequest)request);
String captcha = getCaptcha(request);
boolean mobile = isMobileLogin(request);
return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha, mobile);
}
获取username password rememberMe的信息,然后交给Realm的doGetAuthenticationInfo方法使用
注意需要强转成UsernamePasswordToken
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
doGetAuthenticationInfo认证方法流程
转化为UserNamePasswordToken
根据提供的用户名密码查找数据库信息
逻辑处理
返回给
SimpleAuthenticationInfo
return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()),
user.getPassword(), ByteSource.Util.bytes(salt), getName());
注意返回的SimpleAuthenticationInfo是给授权方法取出的,所以注意参数的注入
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Principal principal = (Principal) getAvailablePrincipal(principals);
doGetAuthorizationInfo授权方法流程
转化Principal,取出用户相关信息
对用户的权限进行查询数据库,取出用户的权限、角色、资源等信息
将信息加入SimpleAuthorizationInfo中并返回
try{
User user = userService.get(new User(principal.getLoginName()));
if (user != null) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// List<Menu> list = SysUtils.getRoleMenu();
// for (Menu menu : list){
// if (StringUtils.isNotBlank(menu.getPermission())){
// // 添加基于Permission的权限信息
// for (String permission : StringUtils.split(menu.getPermission(),",")){
// info.addStringPermission(permission);
// }
// }
// }
// 添加用户权限
info.addStringPermission("user");
// 更新登录IP和时间
// iUserApi.updateUserLoginInfo(user);
// 记录登录日志
// LogUtils.saveLog(Servlets.getRequest(), "系统登录");
return info;
}
添加权限信息,同理添加角色等
info.addStringPermissions(permissions);
info.addStringPermission("user");
返回给
4.登录流程(和spring结合之后)
用户还没有认证时,根据shiroFilterChainDefinitions配置的loginUrl进行登录操作
此时被formAuthenticationFilter拦截取出request中的username和password以及remeberMe等相关信息,然后进行逻辑处理,组装token,返回给realm
realm拿到了token进入了
doGetAuthenticationInfo
方法,查询数据库,进行认证
5退出
<!-- 请求这个地址直接退出并清除session -->
${adminPath}/logout = logout