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中,代码如下:

        /**
	 * user login
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(	AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken authToken = (UsernamePasswordToken) token;
		String accountId =  authToken.getUsername();
		String password = String.valueOf(authToken.getPassword());		
		//登陆方法需要添加 平台参数  系统参数过滤
		AccountQuery query = new AccountQuery();
		query.setAccountId(accountId);
		query.setEmail(accountId);
		query.setMoblie(accountId);
		query.setPlatformId(platformLabel);
		query.setSubSystemId(systemLabel);
                //从数据库中获取账号
                com.isoftstone.securityframework.api.domain.Account domainAccount =
                (com.isoftstone.securityframework.api.domain.Account)accountManagerImpl.getAccount(accountId,platformLabel,systemLabel);
		//判断用户是否存在
		if (null == domainAccount){
			 throw new UnknownAccountException(String.format("账号[%s]不存在!", accountId));
		}
		//检查用户密码是否匹配
		if (!domainAccount.getPassword().equals(password)){
			 throw new IncorrectCredentialsException (String.format("[%s]密码错误!", accountId));
		}
		//检查账号是否激活
		if(STATUS_NOTACTIVATED == domainAccount.getStatus()){
			throw new AuthenticationException (String.format("用户名[%s]未激活!", accountId));
		}
		//检查账号是否已冻结
		if(STATUS_FREEZEEXCED == domainAccount.getStatus()){
			throw new AuthenticationException (String.format("账号[%s]已冻结", accountId));
		}
		//检查账号身份是否冻结
		AccountCommon accountCommon = domainAccount.getAccCommon();
		if(accountCommon!=null){
			if(accountCommon.getIsBuyer()!=4 &&accountCommon.getIsSaler()!=4){
				throw new AuthenticationException (String.format("账号[%s]已经被冻结", accountId));
			}
		}
		//设置登录时间
		domainAccount.setLastLoginTime(DateUtils.getToday(DateUtils.TIMEF_FORMAT));
		accountManagerImpl.modify(domainAccount);
		
		Account  authAccount = new Account();
		this.copyPropertiesToAuthAccount(domainAccount,authAccount);
		
		//设置已认证的用户信息到用户对象中
		SimpleAuthenticationInfo simpleAuthInfo = new SimpleAuthenticationInfo(authAccount,authAccount.getPassword(),getName());
		
		return simpleAuthInfo;
	}

四、授权(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中,代码如下:
        /**
	 * user permission query(Get authorization info from Cache first or get info from remote service ) 
	 */
	@SuppressWarnings("unchecked")
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		Account  account1 = (Account)getAvailablePrincipal(principals);
		com.isoftstone.securityframework.api.domain.Account account = (com.isoftstone.securityframework.api.domain.Account) accountManagerImpl.get(account1.getId());
		//加载权限
                List<com.isoftstone.securityframework.api.Permission> perms = new ArrayList<Permission>();
		//从数据库中查询权限
		perms = rolePermissionRealm.getSubjectPermission(account);
		Set<String> permSet = new HashSet<String>();
		if(null != perms){
			for (Permission perm : perms) {
				String permissionName = perm.getPermissionName();
				//将前缀去掉 
				int beginIndex = platformLabel.length() +systemLabel.length()+2;
				permissionName = permissionName.substring(beginIndex);
				permSet.add(permissionName);
			}
		}
		SimpleAuthorizationInfo simpleAuthInfo = new SimpleAuthorizationInfo();
		simpleAuthInfo.setStringPermissions(permSet);
		return simpleAuthInfo;
	}

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

五、认证和授权小结

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



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值