shiro学习和使用实例(1)

一、shiro是什么

      shiro是一个功能强大且容易使用的java安全框架,用它可以完成认证,授权,加密,会话管理,同时它也支持web集成,多线程,缓存等。


二、shiro的一些基础概念

      Subject:主体,一般就是“用户”。

      SecurityManager:安全管理,它是shiro的核心,管理所有的Subject以及认证,授权,会话管理,缓存等。

      Authenticator:认证器,与身份认证有关。

      Authorizer:授权器,与授权有关。

      Realm:域,它是实现具体的身份认证,授权的地方。

      sessionManager:会话管理器。

      sessionDAO:session数据访问对象。

      cacheManager:缓存控制器,与缓存有关,后面会讲到与redis集成。


三、认证(authentication)

     

     首先ajax请求,将登陆账号和加密密码发送到后台服务器,后台封装包含账号和密码的UsernamePasswordToken对象

     UsernamePasswordToken token = new UsernamePasswordToken(userID,password, false);
     token.setRememberMe(rememberMe);//设置记住我  自动登录
     SecurityUtils.getSubject().login(token);
      通过 SecurityUtils.getSubject()获取主体subject对象,调用login方法,SecurityUtils.getSubject().login(token)实际上它会自动委托给SecurityManager.login方法进行登陆,SecurityManager负责真正的身份验证,具体由认证者Authenticator根据认证策略Authentication strategy进行认证逻辑,Authentication strategy认证策略就是有一个或者多个realm域来实现,它可以是满足一个realm,满足所有realm,满足任意realm,即realm的and/or组合。realm里面写的就是最终的认证逻辑,一般来说就是账号和密码是否匹配,当然还可以有其他的信息,比如说账号是否冻结,是否激活,账号是否存在,如果没有认证通过,就抛出异常信息,如果realm认证成功,要返回一个已认证的用户信息到用户对象中,
SimpleAuthenticationInfo simpleAuthInfo = new SimpleAuthenticationInfo(authAccount,authAccount.getPassword(),getName());
      到这里,认证就结束了。

      具体的认证方法在我们自己实现的realm中,代码如下:

  1.        /** 
  2.  * user login 
  3.  */  
  4. @Override  
  5. protected AuthenticationInfo doGetAuthenticationInfo(   AuthenticationToken token) throws AuthenticationException {  
  6.     UsernamePasswordToken authToken = (UsernamePasswordToken) token;  
  7.     String accountId =  authToken.getUsername();  
  8.     String password = String.valueOf(authToken.getPassword());        
  9.     //登陆方法需要添加 平台参数  系统参数过滤  
  10.     AccountQuery query = new AccountQuery();  
  11.     query.setAccountId(accountId);  
  12.     query.setEmail(accountId);  
  13.     query.setMoblie(accountId);  
  14.     query.setPlatformId(platformLabel);  
  15.     query.setSubSystemId(systemLabel);  
  16.                //从数据库中获取账号  
  17.                com.isoftstone.securityframework.api.domain.Account domainAccount =  
  18.                (com.isoftstone.securityframework.api.domain.Account)accountManagerImpl.getAccount(accountId,platformLabel,systemLabel);  
  19.     //判断用户是否存在  
  20.     if (null == domainAccount){  
  21.          throw new UnknownAccountException(String.format("账号[%s]不存在!", accountId));  
  22.     }  
  23.     //检查用户密码是否匹配  
  24.     if (!domainAccount.getPassword().equals(password)){  
  25.          throw new IncorrectCredentialsException (String.format("[%s]密码错误!", accountId));  
  26.     }  
  27.     //检查账号是否激活  
  28.     if(STATUS_NOTACTIVATED == domainAccount.getStatus()){  
  29.         throw new AuthenticationException (String.format("用户名[%s]未激活!", accountId));  
  30.     }  
  31.     //检查账号是否已冻结  
  32.     if(STATUS_FREEZEEXCED == domainAccount.getStatus()){  
  33.         throw new AuthenticationException (String.format("账号[%s]已冻结", accountId));  
  34.     }  
  35.     //检查账号身份是否冻结  
  36.     AccountCommon accountCommon = domainAccount.getAccCommon();  
  37.     if(accountCommon!=null){  
  38.         if(accountCommon.getIsBuyer()!=4 &&accountCommon.getIsSaler()!=4){  
  39.             throw new AuthenticationException (String.format("账号[%s]已经被冻结", accountId));  
  40.         }  
  41.     }  
  42.     //设置登录时间  
  43.     domainAccount.setLastLoginTime(DateUtils.getToday(DateUtils.TIMEF_FORMAT));  
  44.     accountManagerImpl.modify(domainAccount);  
  45.       
  46.     Account  authAccount = new Account();  
  47.     this.copyPropertiesToAuthAccount(domainAccount,authAccount);  
  48.       
  49.     //设置已认证的用户信息到用户对象中  
  50.     SimpleAuthenticationInfo simpleAuthInfo = new SimpleAuthenticationInfo(authAccount,authAccount.getPassword(),getName());  
  51.       
  52.     return simpleAuthInfo;  
  53. }  

四、授权(authorization)

     由图可见,当调用Subject.isPermitted()或Subject.hasRole()时,shiro会交给Security Manager,然后Security Manager又会将授权交个Authorizer授权者,而Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给ModularRealmAuthorizer 进行循环判断,如果匹配如isPermitted*/hasRole*会返回true,否则返回false表示授权失败。

     如果Realm进行授权的话,应该继承AuthorizingRealm,其流程是:
         1.1、如果调用hasRole*,则直接获取AuthorizationInfo.getRoles()与传入的角色比较即可;
         1.2、首先如果调用如isPermitted(“user:view”),首先通过PermissionResolver 将权限字符串
         转换成相应的Permission 实例,默认使用WildcardPermissionResolver,即转换为通配符的WildcardPermission;
     具体的授权方法在我们自己实现的realm中,代码如下:
  1.        /** 
  2.  * user permission query(Get authorization info from Cache first or get info from remote service )  
  3.  */  
  4. @SuppressWarnings("unchecked")  
  5. @Override  
  6. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
  7.     Account  account1 = (Account)getAvailablePrincipal(principals);  
  8.     com.isoftstone.securityframework.api.domain.Account account = (com.isoftstone.securityframework.api.domain.Account) accountManagerImpl.get(account1.getId());  
  9.     //加载权限  
  10.                List<com.isoftstone.securityframework.api.Permission> perms = new ArrayList<Permission>();  
  11.     //从数据库中查询权限  
  12.     perms = rolePermissionRealm.getSubjectPermission(account);  
  13.     Set<String> permSet = new HashSet<String>();  
  14.     if(null != perms){  
  15.         for (Permission perm : perms) {  
  16.             String permissionName = perm.getPermissionName();  
  17.             //将前缀去掉   
  18.             int beginIndex = platformLabel.length() +systemLabel.length()+2;  
  19.             permissionName = permissionName.substring(beginIndex);  
  20.             permSet.add(permissionName);  
  21.         }  
  22.     }  
  23.     SimpleAuthorizationInfo simpleAuthInfo = new SimpleAuthorizationInfo();  
  24.     simpleAuthInfo.setStringPermissions(permSet);  
  25.     return simpleAuthInfo;  
  26. }  

      当我们调用Subject.isPermitted()进行鉴权的时候,shiro会先去缓存中找当前登录账号的授权信息SimpleAuthorizationInfo,如果没有找到,它会调用上述realm中的doGetAuthorizationInfo(PrincipalCollection principals)方法从数据库中获取权限,然后和页面传过来的权限信息比对,判断是否有权限。对于授权流程,在后面的实例中会结合鉴权有更具体的描述。

五、认证和授权小结      以上是shiro认证和授权的一些原理、流程,对于shiro的基本概念这里讨论的并不是很详细,推荐这个系列博客, 点击打开链接,我从这个博客系列学习到了很多,感谢作者。接下来我会结合具体的项目,整理出shiro的使用思路和实例。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值