Table of contents
Backend Interface Service Annotation
Authorization verification - no role access
Authorization Verification - Obtain a role for verification
Authorization Verification - Obtain permission for verification
Authorization Verification - Exception Handling
authorized
After the user logs in, it needs to verify whether the user has the specified permission of the specified role. Shiro also provides convenient tools for judgment. This tool is Realm's doGetAuthorizationInfo method for judgment.
There are two ways to trigger permission judgment
(1) Judging by the shiro:**** attribute in the page
(2) Judging by annotating @Requires**** in the interface service
Backend Interface Service Annotation
Authorization verification can be realized by adding annotations to interface service methods, which can be added to controller methods or business methods, generally added to controller methods. Commonly used annotations are as follows:
(1)@RequiresAuthentication
Verify whether the user is logged in, equivalent to the method subject.isAuthenticated()
(2)@RequiresUser
Verify whether the user is remembered: If the login authentication is successful, subject.isAuthenticated() is true After logging in, subject.isRemembered() is true
(3)@RequiresGuest
Verify whether it is a guest's request, whether it is a visitor's request, subject.getPrincipal() is null at this time
(4)@RequiresRoles
Verify that the subject has a corresponding role, and if there is a role access method, an exception will be thrown, AuthorizationException. For example:
@RequiresRoles(“aRoleName”)
void someMethod();
Only the subject has the aRoleName role to access the method someMethod()
(5)@RequiresPermissions
Verify that the subject has the corresponding permissions and access methods if it has permission, otherwise an exception will be thrown AuthorizationException. For example:
@RequiresPermissions (“file:read”,”wite:aFile.txt”)
void someMethod();
The subject must have both file:read and write:aFile.txt permissions to access the method someMethod()
Authorization verification - no role access
(1) Add the controller method and add the verification role annotation
//登录认证验证角色
@RequiresRoles("admin")
@GetMapping("userLoginRoles")
@ResponseBody
public String userLoginRoles() {
System.out.println("登录认证验证角色");
return "验证角色成功";
}
(2) Modify main.html
<body>
<h1>Shiro 登录认证后主页面</h1>
<br>
登录用户为:<span th:text="${session.user}"></span>
<br>
<a href="/logout">登出</a>
<br>
<a href="/myController/userLoginRoles">测试授权</a>
</body>
(3) Modify the MyRealm method
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比
@Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入自定义授权方法");
return null;
}
(4) Run the test
Authorization Verification - Obtain a role for verification
(1) Modify the MyRealm method
//自定义授权方法:获取当前登录用户权限信息,返回给 Shiro 用来进行授权对比
@Override
protected AuthorizationInfo
doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("进入自定义授权方法");
//1 创建对象,存储当前登录的用户的权限和角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//2 存储角色
info.addRole("admin");
//返回
return info;
}
(2) Run the test
(3) Confirm library table
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='角色表';
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) Query sql to query the corresponding role information according to the user name
SELECT NAME FROM role WHERE id IN (SELECT rid FROM role_user WHERE uid=(SELECT id FROM USER WHERE NAME='张三'));
(5) mapper method
@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 realization
//获取用户的角色信息
@Override
public List<String> getUserRoleInfo(String principal) {
return userMapper.getUserRoleInfoMapper(principal);
}
(7) MyRealm method modification
//自定义授权方法:获取当前登录用户权限信息,返回给 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) Start the login test
Authorization Verification - Obtain permission for verification
Obtaining permission verification is similar to obtaining roles
(1) Confirm the library table
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='权限表';
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) Query sql to query the corresponding permission information according to the role name
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 method
@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 realization
//获取用户角色的权限信息
@Override
public List<String> getUserPermissionInfo(List<String> roles) {
return userMapper.getUserPermissionInfoMapper(roles);
}
(5) MyRealm method modification
//自定义授权方法:获取当前登录用户权限信息,返回给 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) Add controller method
//登录认证验证权限
@RequiresPermissions("user:delete")
@GetMapping("userPermissions")
@ResponseBody
public String userLoginPermissions() {
System.out.println("登录认证验证权限");
return "验证权限成功";
}
(7) Transform main.html
<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) Start the login test
Authorization Verification - Exception Handling
(1) Create an authentication exception handling class and use @ControllerAdvice plus @ExceptionHandler to implement special exception handling.
@ControllerAdvice
public class PermissionsException {
@ResponseBody
@ExceptionHandler(UnauthorizedException.class)
public String unauthorizedException(Exception ex){
return "无权限";
}
@ResponseBody
@ExceptionHandler(AuthorizationException.class)
public String authorizationException(Exception ex){
return "权限认证失败";
}