前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >基于springboot注解的shiro 授权及角色认证

基于springboot注解的shiro 授权及角色认证

作者头像
一个风轻云淡
发布2023-10-15 10:41:00
发布2023-10-15 10:41:00
44900
代码可运行
举报
文章被收录于专栏:java学习javajava学习java
运行总次数:0
代码可运行

授权

用户登录后,需要验证是否具有指定角色指定权限。Shiro也提供了方便的工具进行判 断。 这个工具就是Realm的doGetAuthorizationInfo方法进行判断。

触发权限判断的有两种 方式

(1) 在页面中通过shiro:****属性判断

(2) 在接口服务中通过注解@Requires****进行判断

后端接口服务注解

通过给接口服务方法添加注解可以实现权限校验,可以加在控制器方法上,也可以加 在业务方法上,一般加在控制器方法上。常用注解如下:

(1)@RequiresAuthentication

验证用户是否登录,等同于方法subject.isAuthenticated()

(2)@RequiresUser

验证用户是否被记忆: 登录认证成功subject.isAuthenticated()为true 登录后被记忆subject.isRemembered()为true

(3)@RequiresGuest

验证是否是一个guest的请求,是否是游客的请求 此时subject.getPrincipal()为null

(4)@RequiresRoles

验证subject是否有相应角色,有角色访问方法,没有则会抛出异常 AuthorizationException。 例如:

@RequiresRoles(“aRoleName”) void someMethod();

只有subject有aRoleName角色才能访问方法someMethod()

(5)@RequiresPermissions

验证subject是否有相应权限,有权限访问方法,没有则会抛出异常 AuthorizationException。 例如:

@RequiresPermissions (“file:read”,”wite:aFile.txt”) void someMethod();

subject必须同时含有file:read和wite:aFile.txt权限才能访问方法someMethod()

授权验证-没有角色无法访问

(1)添加 controller 方法,并添加验证角色注解 

代码语言:javascript
代码运行次数:0
运行
复制
//登录认证验证角色 
@RequiresRoles("admin") 
@GetMapping("userLoginRoles") 
@ResponseBody 
public String userLoginRoles() { 
 System.out.println("登录认证验证角色"); 
 return "验证角色成功"; 
}

(2)修改 main.html

代码语言:javascript
代码运行次数:0
运行
复制
<body> 
 <h1>Shiro 登录认证后主页面</h1> 
 <br> 
 登录用户为:<span th:text="${session.user}"></span> 
 <br> 
 <a href="/logout">登出</a> 
<br> 
 <a href="/myController/userLoginRoles">测试授权</a> 
</body>

(3)修改 MyRealm 方法

代码语言:javascript
代码运行次数:0
运行
复制
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 return null; 
} 

(4)运行测试

授权验证-获取角色进行验证 

(1)修改 MyRealm 方法 

代码语言:javascript
代码运行次数:0
运行
复制
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 //1 创建对象,存储当前登录的用户的权限和角色 
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
 //2 存储角色 
 info.addRole("admin"); 
 //返回 
 return info; 
} 

(2)运行测试

 (3)确认库表

代码语言:javascript
代码运行次数:0
运行
复制
CREATE TABLE `role` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `name` VARCHAR(30) DEFAULT NULL COMMENT '角色名', 
 `desc` VARCHAR(50) DEFAULT NULL COMMENT '描述', 
 `realname` VARCHAR(20) DEFAULT NULL COMMENT '角色显示名', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色表'; 
代码语言:javascript
代码运行次数:0
运行
复制
CREATE TABLE `role_user` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `uid` BIGINT(20) DEFAULT NULL COMMENT '用户 id', 
 `rid` BIGINT(20) DEFAULT NULL COMMENT '角色 id', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色用户映射表'; 

 (4)查询 sql 根据用户名查询对应角色信息

SELECT NAME FROM role WHERE id IN (SELECT rid FROM role_user WHERE uid=(SELECT id FROM USER WHERE NAME='张三'));

 (5)mapper 方法

代码语言:javascript
代码运行次数:0
运行
复制
@Repository 
public interface UserMapper extends BaseMapper<User> { 
 @Select("SELECT NAME FROM role WHERE id IN (SELECT rid FROM 
role_user WHERE uid=(SELECT id FROM USER WHERE NAME=#{principal}))") 
 List<String> getUserRoleInfoMapper(@Param("principal") String 
principal); 
}

(6)service 实现

代码语言:javascript
代码运行次数:0
运行
复制
//获取用户的角色信息 
@Override 
public List<String> getUserRoleInfo(String principal) { 
 return userMapper.getUserRoleInfoMapper(principal); 
} 

 (7)MyRealm 方法改造

代码语言:javascript
代码运行次数:0
运行
复制
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 //获取当前用户身份信息 
 String principal = 
principalCollection.getPrimaryPrincipal().toString(); 
 //调用接口方法获取用户的角色信息 
 List<String> roles = userService.getUserRoleInfo(principal); 
 System.out.println("当前用户角色信息:"+roles); 
 //创建对象,存储当前登录的用户的权限和角色 
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
 //存储角色 
 info.addRoles(roles); 
 //返回 
 return info; 
} 

(8)启动登录测试

授权验证-获取权限进行验证

获取权限验证和获取角色相类似

(1)确认库表

代码语言:javascript
代码运行次数:0
运行
复制
CREATE TABLE `permissions` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `name` VARCHAR(30) DEFAULT NULL COMMENT '权限名', 
 `info` VARCHAR(30) DEFAULT NULL COMMENT '权限信息', 
 `desc` VARCHAR(50) DEFAULT NULL COMMENT '描述', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='权限表';
代码语言:javascript
代码运行次数:0
运行
复制
CREATE TABLE `role_ps` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `rid` BIGINT(20) DEFAULT NULL COMMENT '角色 id', 
 `pid` BIGINT(20) DEFAULT NULL COMMENT '权限 id', 
 PRIMARY KEY (`id`) 
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='角色权限映射表`

(2)查询 sql 根据角色名查询对应权限信息

SELECT info FROM permissions WHERE id IN (SELECT pid FROM role_ps WHERE rid IN (SELECT id FROM role WHERE NAME IN('admin','userMag')));

(3)mapper 方法

代码语言:javascript
代码运行次数:0
运行
复制
@Select({ 
 "<script>", 
 "select info FROM permissions WHERE id IN ", 
 "(SELECT pid FROM role_ps WHERE rid IN (", 
 "SELECT id FROM role WHERE NAME IN ", 
 "<foreach collection='roles' item='name' open='(' 
separator=',' close=')'>", 
 "#{name}", 
 "</foreach>", 
 "))", 
 "</script>" 
}) 
List<String> getUserPermissionInfoMapper(@Param("roles")List<String> 
roles);

 (4)service 实现

代码语言:javascript
代码运行次数:0
运行
复制
//获取用户角色的权限信息 
@Override 
public List<String> getUserPermissionInfo(List<String> roles) { 
 return userMapper.getUserPermissionInfoMapper(roles); 
}

(5)MyRealm 方法改造

代码语言:javascript
代码运行次数:0
运行
复制
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比 
@Override 
protected AuthorizationInfo 
doGetAuthorizationInfo(PrincipalCollection principalCollection) { 
 System.out.println("进入自定义授权方法"); 
 //获取当前用户身份信息 
 String principal = 
principalCollection.getPrimaryPrincipal().toString(); 
 //调用接口方法获取用户的角色信息 
 List<String> roles = userService.getUserRoleInfo(principal); 
 System.out.println("当前用户角色信息:"+roles); 
 //调用接口方法获取用户角色的权限信息 
 List<String> permissions = 

userService.getUserPermissionInfo(roles); 
 System.out.println("当前用户权限信息:"+permissions); 
 //创建对象,存储当前登录的用户的权限和角色 
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 
 //存储角色 
 info.addRoles(roles); 
 //存储权限信息 
 info.addStringPermissions(permissions); 
 //返回 
 return info; 
}

(6)添加 controller 方法

代码语言:javascript
代码运行次数:0
运行
复制
//登录认证验证权限 
@RequiresPermissions("user:delete") 
@GetMapping("userPermissions") 
@ResponseBody 
public String userLoginPermissions() { 
 System.out.println("登录认证验证权限"); 
 return "验证权限成功"; 
}

(7)改造 main.html

代码语言:javascript
代码运行次数:0
运行
复制
<body> 
 <h1>Shiro 登录认证后主页面</h1> 
 <br> 
 登录用户为:<span th:text="${session.user}"></span> 
 <br> 
 <a href="/logout">登出</a> 
 <br> 
 <a href="/myController/userLoginRoles">测试授权-角色验证</a> 
 <br> 
 <a href="/myController/userPermissions">测试授权-权限验证</a> 
</body> 

 (8)启动登录测试

授权验证-异常处理

(1)创建认证异常处理类,使用@ControllerAdvice 加@ExceptionHandler 实现特殊异 常处理。

代码语言:javascript
代码运行次数:0
运行
复制
@ControllerAdvice 
public class PermissionsException { 
 @ResponseBody 
 @ExceptionHandler(UnauthorizedException.class) 
 public String unauthorizedException(Exception ex){ 
 return "无权限"; 
 } 
 
 @ResponseBody 
 @ExceptionHandler(AuthorizationException.class) 
 public String authorizationException(Exception ex){ 
 return "权限认证失败"; 
 } 
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 授权
    • 后端接口服务注解
    • 授权验证-没有角色无法访问
    • 授权验证-获取角色进行验证 
    • 授权验证-获取权限进行验证
    • 授权验证-异常处理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档