您当前的位置: 首页 > 

Charge8

暂无认证

  • 0浏览

    0关注

    447博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Shiro 基于权限授权的简单应用与授权注解

Charge8 发布时间:2019-04-25 11:17:17 ,浏览量:0

上篇文章有必要看一下:Shiro 基于角色授权的简单应用与权限过滤器配置含义

一、基于权限授权的简单应用

数据库:

     

    用户admin, 只拥有角色 admin 和 user 与访问  /admin/userlist 的权限资源,如果 pid 为1和2,则两者都可访问。

1、spring.xml 在配置 shiro 的过滤器上,配置权限控制的拦截规则:

        注意:规则是有顺序的,从上到下,拦截范围必须是从小到大的

    
    
    	  
		
		 
		  
		
		  
		 
		  
		  
		
			
				
				/login = anon
				/logout = logout
				/admin/userlist = perms[userlist]
				/admin/addUser = perms[addUser]
				/admin/** = authc    
				/**= anon  
			
		 
	

2、自定义 ShiroRealm类的继承 AuthorizingRealm 类:

      登录认证方法不用修改,授权认证方法做相应修改

	/**
	 * 在 shiro 中专门做授权认证的方法
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {		
		//1 从参数 principals 中获取当前登录成功后的用户信息
		User user = principals.oneByType(User.class);
		//2 根据第一步中的用户信息,获取角色信息(若用户信息包含角色/权限信息,直接取出,若没有,从数据库中获取)
		Set roles = RoleMapper.getRolesByUserid(user.getId());
		// 通过用户关联的role信息,获取角色关联的 permisssion信息
		Set permissions = permissionMapper.getPermissionsByUserid(user.getId());
		
		//3 把获取到的登录用户关联的角色和权限资源信息注入到返回的SimpleAuthorizationInfo对象中
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.addRoles(roles);
		info.addStringPermissions(permissions);
		return info;
	}

PermissionMapper 方法:

	
		select
			p.pname
		from 
			 t_user u,t_role r,t_user_role ur,t_permission p,t_role_permission rp
		where
			u.id=ur.userid and ur.roleid=r.id and r.id=rp.rid and rp.pid=p.id
			and u.id = #{userid}
	

3、登录访问项目

     结果和数据库分析一致

二、Shiro 的授权注解 

1、5个授权注解

        @RequiresRoles(value = {"admin","user"},logical = Logical.AND)

        当前Subject必须拥有所有指定的角色时,才能访问被该注解标注的方法。如果当Subject不同时拥有所有指定角色,则方法不会执行还会抛出AuthorizationException异常。

        @RequiresPermissions(value = {"userlist","userlist2"},logical=Logical.OR)

        当前Subject需要拥有某些特定的权限时,才能执行被该注解标注的方法。如果当前Subject不具有这样的权限,则方法不会被执行。

        认证通过后接受 Shiro 授权检查,授权验证时,需要先判断当前角色是否拥有该权限,只有授权通过,才可以访问受保护 URL 对应的资源,否则跳转到“未经授权页面”。

        @RequiresAuthentication

        用于表明当前用户需是经过认证的用户。使用该注解标注的类/实例/方法在访问或调用时,要求当前Subject 必须在当前的session 中被认证通过才能被访问或调用。即 Subjec.isAuthenticated()返回 true。

        @RequiresUser

        该注解需要当前的Subject 是一个应用程序用户才能被注解的类/实例/方法访问或调用。一个“应用程序用户”被定义为一个拥有已知身份,或在当前session 中由于通过验证被确认,或者在之前session 中的'RememberMe'服务被记住。

        @RequiresGuest

        使用该注解标注的类/实例/方法在访问或调用时,当前Subject可以是“gust”身份,不需要经过认证或者在原先的session中存在记录,即游客身份。

     

2、使用方法

        Shiro 的授权注解处理是有内定的处理顺序的,如果有多个注解的话,前面的通过了会继续检查后面的,若不通过则直接返回,处理顺序依次为(与实际声明顺序无关):

RequiresRoles 
RequiresPermissions 
RequiresAuthentication 
RequiresUser 
RequiresGuest

例如:你如果同时声明了 RequiresRoles 和 RequiresPermissions 注解,那就要求拥有此角色的同时还得拥有相应的权限。

三、基于权限授权的简单注解应用

  使用注解 实现 第一点 的功能

1、spring.xml 在配置 shiro 的过滤器上

      取消配置权限控制的拦截规则,

      添加一个SimpleMappingExceptionResolver异常处理。

    
    
    	  
		
		 
		  
		
		  
		 
		  
		
	
	
		
			
				unauthorized
				login
			
		
	

2、自定义 ShiroRealm类的继承 AuthorizingRealm 类:和第一点相同处理

3、action 类中进行注解授权:

	@RequiresGuest
	@GetMapping(value= {"/","/login"})
	public String login(Model model, HttpSession session) {
		//生成一组16位随机数
		int hashCodeValue = UUID.randomUUID().hashCode();
		if(hashCodeValue < 0) hashCodeValue = -hashCodeValue;
		String uuidSalt = String.format("%016d",hashCodeValue);//左边补0,16位,进制(d,x)
		
		//把uuid盐值,同时保存在前后端
		model.addAttribute("uuidSalt", uuidSalt);
		session.setAttribute("uuidSalt", uuidSalt);
		return "login";
	}
	
	@RequiresGuest
	@PostMapping("/login")
	public String login(User user, HttpSession session) {
		//使用 shiro 登录验证
		//1 认证的核心组件:获取 Subject 对象
		Subject subject = SecurityUtils.getSubject();
				
		//2 将登陆表单封装成 token 对象
		UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPazzword());
		try {
			//3 让 shiro 框架进行登录验证:
			subject.login(token);
		} catch (Exception e) {
			e.printStackTrace();
			return "loginError";
		}
		return "redirect:/admin/index";
	}
	
	@RequiresAuthentication
	@GetMapping("/admin/index")
	public String admin(Model model) {
		return "admin/index";
	}
	
	@RequiresPermissions(value = {"userlist","userlist2"},logical=Logical.OR)
	@GetMapping("/admin/userlist")
	public String userlist() {
		return "admin/userlist";
	}
	
	@RequiresPermissions(value = {"addUser"})
	@GetMapping("/admin/addUser")
	public String addUser() {
		return "admin/addUser";
	}
	
	@GetMapping("/unauthorized")
	public String unauthorized() {
		return "unauthorized";
	}
	
	/**
	 * shrio 使用注解之后,需要自己实现退出
	 */
	@GetMapping("/logout")
	public String logout() {
		SecurityUtils.getSubject().logout(); //实现退出
		return "redirect:/login";
	}

4、登录访问项目:

   结果和上面一致

注意:使用注解后的2个问题

1、退出登录需要自己实现(SecurityUtils.getSubject().logout();)。

2、没有登录认证访问无访问权限的页面后的跳转要自己配置实现(添加一个SimpleMappingExceptionResolver异常处理)。

不处理这两个问题会出现这个:

 

 

 5、测试一下同时声明了 RequiresRoles 和 RequiresPermissions 注解

	@RequiresRoles(value = {"admin2","user"},logical=Logical.AND)
	@RequiresPermissions(value = {"userlist","userlist2"},logical=Logical.OR)
	@GetMapping("/admin/userlist")
	public String userlist() {
		System.out.println("admin");
		return "admin/userlist";
	}

    用户 admin,拥有 admin 和 user 角色,userlist  权限资源,所以上面会跳转到 无访问权限 页面。

    把 RequiresRoles 中 admin2 改为 admin 时, 认证通过,能够访问 /admin/userlist  权限资源。

 

end ~

 

 

 

关注
打赏
1664721914
查看更多评论
立即登录/注册

微信扫码登录

0.0424s