Shiro authorization and role authentication based on springboot annotations

Table of contents

authorized

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 "权限认证失败"; 
 } 

Guess you like

Origin blog.csdn.net/m0_62436868/article/details/130679164