One:Shiro的认证与授权

本文核心:RBAC权限模型,Shiro与Spring的整合,Shiro认证与授权【集成到项目中】。

 

这系列博客是记录自己做过项目学到知识。one、two代表项目编号。

 

前言:

后台管理系统

技术选型:ssm + easyui + ajax + js/jq + jsp + mysql + redis

工具版本:jdk1.8 + tomcat7/8 + mysql8.0.11 + idea2017 + spring4.1.13

项目规范:maven3.3.9 + git

 

shiro认证与授权可以通过配置shiro.ini文件。这里采用Shrio与Spring项目集成的方式,将Shiro的配置文件配置到Spring配置文件中。

 

 

一:RBAC权限模型【管理系统权限】

首先介绍一下,什么是认证,什么是授权。

 

认证:

Subject:主体

访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体。

Principal:身份信息

是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。

credential:凭证信息

是只有主体自己知道的安全信息,如密码、证书等。

token(令牌):身份信息+凭证信息的组合=一个令牌

 

授权:

Who,即主体(Subject),主体需要访问系统中的资源。

What,即资源(Resource),如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为t01的商品为资源实例,编号为001的商品信息也属于资源实例。

How,权限/许可(Permission),规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作许可

 

 

 

RBAC认为权限的过程可以抽象概括为:判断【Who是否可以对What进行How的访问操作(Operator)】这个逻辑表达式的值是否为True的求解过程。

即将权限问题转换为Who、What、How的问题。who、what、how构成了访问权限三元组。

权限模型:

One:Shiro的认证与授权_第1张图片

 

我们的数据库权限设计,需要五张表。这张图我已经详细解释了如何查询用户的角色和权限。【不补充数据库设计和Mapper文件的写法。】

 

 

 

二:Shiro与Spring整合   

 

首先导入Shiro依赖和Shiro与Spring整合依赖 【默认已完成SSM项目框架搭建】




   org.apache.shiro
   shiro-core
   1.3.1




   org.apache.shiro
   shiro-web
   1.3.1




   org.apache.shiro
   shiro-spring
   1.3.1




   org.apache.shiro
   shiro-ehcache
   1.2.6

 

 

Web.xml配置 shiro的过滤器【Filter过滤器配置顺序即调用链传递的顺序,个人建议:如果配置SpringMVC自带的字符过滤器应放在Shiro过滤器前面。



   shiroFilter
   org.springframework.web.filter.DelegatingFilterProxy
   
      targetBeanName
      shiroFilter
   


   shiroFilter
   /*

其中的  配置指向 application-context-shiro.xml的配置文件的一个bean

 

 

application-context-shiro.xml的配置文件


   
   
      
      
         
            
         
      
   

   
   
      
   

   
   
      
      
      
      
   


   
   
      
      
      
      
      
      
      
         
            /Login_Jsp/login.jsp=anon
            /Main_Jsp/main/main.jsp=authc
            /**=anon
         
      
   

 

重点理解掌握 【过滤器的取值的含义】

过滤器:anon |不认证就可以访问资源 org.apache.shiro.web.filter.authc.AnonymousFilter 
      authc |表单认证  org.apache.shiro.web.filter.authc.FormAuthenticationFilter
      user  |用户认证成功或记住我 org.apache.shiro.web.filter.authc.UserFilter
      logout|登出过滤器  org.apache.shiro.web.filter.authc.LogoutFilter
      roles |角色授权过滤器 org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
      perms |权限授权过滤器 org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
      port	|端口过滤器   org.apache.shiro.web.filter.authz.PortFilter 
      ssl	|https过滤器  org.apache.shiro.web.filter.authz.SslFilter 
      rest	|restful风格过滤器  org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter       

提示:我们将Shiro的配置单独为一个文件,因此需要将Shiro的配置文件导入Spring配置文件中。【代码省略】

 

 

 

 

三:自定义复杂的凭证匹配器

MyRealm 继承AuthorizingRealm 类,需要实现两个抽象方法。

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)//认证方法
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection)//授权方法

 

认证的过程:

 

①Controller接收参数用户名密码,web环境下获取主体,调用主体的Login方法。

        @RequestMapping("/login")
	public @ResponseBody String managerLogin(String managerName, String managerPwd, String enCode, HttpSession session){
		//先判断验证码是否正确
		String code=(String)session.getAttribute("code");
		if(code.equalsIgnoreCase(enCode)) {
			// 在web环境中安全管理器会自动进行初始化
			// 获取主体
			Subject subject = SecurityUtils.getSubject();
			try {
				subject.login(new UsernamePasswordToken(managerName,managerPwd));
				session.setAttribute("managerName",managerName);
				return "success";
			} catch (Exception e) {
				e.printStackTrace();
				return "loser";
			}
		}else{
			return "loser";
		}
	}

 

 

②  中间经过一系列的包装,方法走到doGetAuthenticationInfo【认证】,验证账号密码是否正确

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
   //首先强转为UsernamePasswordToken  可以获取到用户名->查询数据库->验证
   UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;
   String managerName=token.getUsername();
   
   Manager manager=managerService.queryManagerByName(managerName);
   if (manager!=null){
      return new SimpleAuthenticationInfo(managerName,
            manager.getManagerPwd(),
            ByteSource.Util.bytes(manager.getManagerSalt()),
            UUID.randomUUID().toString());
   }
   return null;
}

验证方法返回的SimpleAuthenticationInfo对象的四个参数: 用户名,加密后的密码,加密的盐,无重复的数。【采用哪种加密算法和散列运算的次数在配置文件中配置】  参考application-context-shiro.xml。

 

验证失败会以异常的形式抛出 【罗列常见的两种异常,我们可以捕获异常给予用户友好的提示。】

UnknownAccountException
账号不存在异常如下:
org.apache.shiro.authc.UnknownAccountException: No account found for user。。。。

IncorrectCredentialsException
当输入密码错误会抛此异常,如下:
org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - zhangsan, rememberMe=false] did not match the expected credentials.

 

 

 

 

授权的过程  【获取用户名->查询数据库->绑定角色、权限】

 

提示,只有先认证成功,才会走到授权这一步。

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		//获取用户名 【登陆账号】
		String username = (String) principalCollection.getPrimaryPrincipal();
		List list=managerService.queryRole(username);
                //这里只查询了角色
		if(list!=null){
			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
			for (Role role : list) {
				info.addRole(role.getRoleName());
			}
			return info;
		}
		return null;
	}

 

在JSP页面我们一通过Shiro定义的标签轻松判断用户拥有哪些权限和角色,通过标签来控制页面的展示信息。

 

标签的使用和相关功能【18年7月14日 补充】

//JSP页面引入shiro标签库
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
        //判断用户是否为游客
	//判断用户是否已经登录(包括已认证和已记住)
	//判断用户是否具有某个角色
	//判断用户是否缺少某个角色
	>//判断用户是否具有任意某个角色
	//判断用户是否具有某个权限
	//判断用户是否缺少某个权限

 

 

 

 

 

你可能感兴趣的:(项目笔记)