The use of shiro in springboot and the implementation of permission management

Using Shiro with Spring Boot:

1. Add Shiro dependency

Add the following dependencies in Maven:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.4.2</version>
</dependency>

2. Configure Shiro

application.propertiesAdd the following configuration to the file :

# Shiro配置
shiro:
  # 启用Shiro
  enabled: true
  # 配置Realm
  realm:
    # 指定自定义的Realm类
    type: com.example.demo.shiro.CustomRealm
  # 配置加密算法
  credentialsMatcher:
    hashAlgorithmName: md5
    hashIterations: 2

3. Implement custom Realm

Create a CustomRealmclass, inherit AuthorizingRealm, and implement doGetAuthenticationInfo()and doGetAuthorizationInfo()methods.

public class CustomRealm extends AuthorizingRealm {

    /**
     * 用户认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取用户名和密码
        String username = (String) authenticationToken.getPrincipal();
        String password = new String((char[]) authenticationToken.getCredentials());
        
        // 根据用户名查询用户信息
        User user = userService.findUserByUsername(username);
        if (user == null) {
            throw new UnknownAccountException();
        }
        
        // 校验密码
        if (!password.equals(user.getPassword())) {
            throw new IncorrectCredentialsException();
        }
        
        // 返回认证信息
        return new SimpleAuthenticationInfo(user, password, getName());
    }

    /**
     * 用户授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 获取当前用户信息
        User user = (User) principalCollection.getPrimaryPrincipal();
        
        // 获取用户角色和权限信息
        List<Role> roles = userService.findRolesByUserId(user.getId());
        List<Permission> permissions = userService.findPermissionsByUserId(user.getId());
        
        // 添加角色和权限信息到授权信息中
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        for (Role role : roles) {
            authorizationInfo.addRole(role.getName());
        }
        for (Permission permission : permissions) {
            authorizationInfo.addStringPermission(permission.getName());
        }
        
        // 返回授权信息
        return authorizationInfo;
    }
}

4. Use Shiro for authentication

Where identity authentication is required, such as in the Controller, the following code can be used for authentication:

@PostMapping("/login")
public String login(String username, String password) {
    // 创建用户名密码Token
    UsernamePasswordToken token = new UsernamePasswordToken(username, password);
    
    // 获取Subject
    Subject subject = SecurityUtils.getSubject();
    
    try {
        // 登录
        subject.login(token);
        
        // 认证成功
        return "redirect:/home";
    } catch (AuthenticationException e) {
        // 认证失败
        return "redirect:/login?error=true";
    }
}

5. Use Shiro for permission control

Where permission control is required, such as methods in Controller, the following annotations can be used for control:

@RequiresPermissions("user:list")
@GetMapping("/users")
public String listUsers() {
    // 查询用户列表
    List<User> userList = userService.findAllUsers();
    
    // 返回用户列表页面
    return "users";
}

In Shiro, @RequiresPermissionsannotations can be used to restrict user access rights. The specific steps are as follows:

  1. define permissions

In Shiro, permissions are usually represented by strings, and permission strings can be defined according to application scenarios. For example, userthe following permissions can be defined under a module:

  • user:list: view user list
  • user:add:New users
  • user:edit: edit user
  • user:delete:delete users

        2. Authorize in Realm

In the method of Realm doGetAuthorizationInfo(), the permission string owned by the user can be added to the authorization information according to the user's role, permission and other information. For example, CustomRealmthe following code can be implemented in:

@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    // 获取当前用户信息
    User user = (User) principalCollection.getPrimaryPrincipal();
    
    // 获取用户角色和权限信息
    List<Role> roles = userService.findRolesByUserId(user.getId());
    List<Permission> permissions = userService.findPermissionsByUserId(user.getId());
    
    // 添加角色和权限信息到授权信息中
    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    for (Role role : roles) {
        authorizationInfo.addRole(role.getName());
    }
    for (Permission permission : permissions) {
        authorizationInfo.addStringPermission(permission.getName());
    }
    
    // 返回授权信息
    return authorizationInfo;
}

        3. Use permission control in the Controller method

On methods that require permission control, use @RequiresPermissionsannotations to specify the required permissions. For example, UserControllerthe following code can be implemented in:

@RequiresPermissions("user:list")
@GetMapping("/users")
public String listUsers(Model model) {
    // 查询用户列表
    List<User> userList = userService.findAllUsers();
    
    // 将用户列表添加到Model中
    model.addAttribute("userList", userList);
    
    // 返回用户列表页面
    return "users";
}

@RequiresPermissions("user:add")
@PostMapping("/users")
public String addUser(User user) {
    // 新增用户
    userService.addUser(user);
    
    // 返回用户列表页面
    return "redirect:/users";
}

@RequiresPermissions("user:edit")
@PutMapping("/users/{id}")
public String editUser(@PathVariable("id") Long id, User user) {
    // 更新用户信息
    userService.updateUser(id, user);
    
    // 返回用户列表页面
    return "redirect:/users";
}

@RequiresPermissions("user:delete")
@DeleteMapping("/users/{id}")
public String deleteUser(@PathVariable("id") Long id) {
    // 删除用户
    userService.deleteUser(id);
    
    // 返回用户列表页面
    return "redirect:/users";
}

In the above code, @RequiresPermissionsannotations are used to limit /usersthe permissions required by different HTTP methods under the user access path, such as list, add, edit, delete. An exception will be thrown if the user does not have sufficient permissions UnauthorizedException.

When we use Shiro for user permission control, we usually need to create the following tables in the database:

1. User table ( user)

It is used to store basic information of system users, including user names, passwords, etc.

CREATE TABLE `user` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `username` VARCHAR(50) NOT NULL,
  `password` VARCHAR(100) NOT NULL,
  PRIMARY KEY (`id`)
);

2. Role table ( role)

It is used to store the basic information of system roles, including role name, description, etc.

CREATE TABLE `role` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) NOT NULL,
  `description` VARCHAR(100),
  PRIMARY KEY (`id`)
);

3. Permission table ( permission)

Used to store basic information about system permissions, including permission name, description, etc.

CREATE TABLE `permission` (
  `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) NOT NULL,
  `description` VARCHAR(100),
  PRIMARY KEY (`id`)
);

4. User role association table ( user_role)

It is used to store the association information between system users and roles.

CREATE TABLE `user_role` (
  `user_id` BIGINT(20) NOT NULL,
  `role_id` BIGINT(20) NOT NULL,
  PRIMARY KEY (`user_id`, `role_id`),
  CONSTRAINT `fk_user_role_user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
  CONSTRAINT `fk_user_role_role_id` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`)
);

5. Role permission association table ( role_permission)

It is used to store the associated information of system roles and permissions.

CREATE TABLE `role_permission` (
  `role_id` BIGINT(20) NOT NULL,
  `permission_id` BIGINT(20) NOT NULL,
  PRIMARY KEY (`role_id`, `permission_id`),
  CONSTRAINT `fk_role_permission_role_id` FOREIGN KEY (`role_id`) REFERENCES `role` (`id`),
  CONSTRAINT `fk_role_permission_permission_id` FOREIGN KEY (`permission_id`) REFERENCES `permission` (`id`)
);

以上就是shiro的基本使用啦~~

Guess you like

Origin blog.csdn.net/qq_56921846/article/details/132662931