springboot集成shiro实现权限管理

springboot集成shiro实现权限管理

本文是基于前面两篇文章的,如果还不了解的可以回头去看看:

1、springboot集成shiro实现用户登录认证
2、springboot集成shiro实现RemeberMe

前面已经实现了登录认证和RemeberMe两个功能,今天我们来学习一下怎么实现权限管理,毕竟使用shiro的理由就是它的权限管理功能。

依赖

依赖、配置都和前面的一样。
这里不再赘述

ShiroRealm

修改ShiroRealm
这次我们将doGetAuthorizationInfo(PrincipalCollection principal)这个方法用起来了。它主要就是用来获取用户权限和角色的。

/**
     * 获取用户角色和权限
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        String username = user.getUsername();
        System.out.println("用户" + username + "获取权限");
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //获取用户角色集

        List<Role> roles = userRoleMapper.findByUsername(username).getRoleid();
        Set<String> roleset = new HashSet<>();
        for (Role r : roles){
            roleset.add(r.getName());
        }
        simpleAuthorizationInfo.setRoles(roleset);
        List<Permission> permissions = new ArrayList<>();
        //获取用户权限集
        Set<String> perset = new HashSet<>();
        for (Role role: roles){
            permissions = role.getPermissionid();
            for (Permission p : permissions){
                perset.add(p.getName());
            }
        }


        simpleAuthorizationInfo.setStringPermissions(perset);
        return simpleAuthorizationInfo;
    }

数据层

User.java

@Entity
@Table(name = "user")
public class User implements Serializable {
    private static final long serialVersionUID = 6383802229128937351L;
    @Id
    @GeneratedValue
    private Integer id;
    private String username;
    private String password;
    private Date create_time;
    private String status;
    @ManyToMany //多对多的关系
    @JoinTable(name = "user_role", joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
    private List<Role> roleid;
    //get...
    //set...
    }

Role.java

@Entity
@Table(name = "role")
public class Role implements Serializable {

    private static final long serialVersionUID = -5912189689012817664L;
    @Id
    @GeneratedValue
    private Integer id;
    private String name;
    private String memo;
    @ManyToMany
    @JoinTable(name = "role_permission", joinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")}, inverseJoinColumns = {@JoinColumn(name = "permission_id", referencedColumnName = "id")})
    private List<Permission> permissionid;
    //set
    //get
    }

Permission.java

@Entity
@Table(name = "permission")
public class Permission implements Serializable {

    private static final long serialVersionUID = 1774676761003524456L;
    @Id
    @GeneratedValue
    private Integer id;
    private String url;
    private String name;
    //get
    //set
    }

以上就是我们的数据层,

SQL
直接贴出SQL吧,如果没有自动建表,那就用SQL来建一下

/*
 Navicat MySQL Data Transfer

 Source Server         : mysql
 Source Server Type    : MySQL
 Source Server Version : 50515
 Source Host           : localhost:3306
 Source Schema         : shiro

 Target Server Type    : MySQL
 Target Server Version : 50515
 File Encoding         : 65001

 Date: 25/07/2018 22:48:40
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for hibernate_sequence
-- ----------------------------
DROP TABLE IF EXISTS `hibernate_sequence`;
CREATE TABLE `hibernate_sequence`  (
  `next_val` bigint(20) NULL DEFAULT NULL
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Fixed;

-- ----------------------------
-- Records of hibernate_sequence
-- ----------------------------
INSERT INTO `hibernate_sequence` VALUES (1);
INSERT INTO `hibernate_sequence` VALUES (1);
INSERT INTO `hibernate_sequence` VALUES (1);

-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission`  (
  `id` int(11) NOT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES (1, 'user:user', '/user');
INSERT INTO `permission` VALUES (2, 'user:add', '/user/add');
INSERT INTO `permission` VALUES (3, 'user:delete', '/user/delete');

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role`  (
  `id` int(11) NOT NULL,
  `memo` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES (1, '超级管理员', 'admin');
INSERT INTO `role` VALUES (2, '测试账户', 'test');

-- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission`  (
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) NOT NULL,
  INDEX `FKf8yllw1ecvwqy3ehyxawqa1qp`(`permission_id`) USING BTREE,
  INDEX `FKa6jx8n8xkesmjmv6jqug6bg68`(`role_id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = latin1 COLLATE = latin1_swedish_ci ROW_FORMAT = Fixed;

-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES (1, 2);
INSERT INTO `role_permission` VALUES (1, 3);
INSERT INTO `role_permission` VALUES (2, 1);
INSERT INTO `role_permission` VALUES (1, 1);

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `create_time` date NULL DEFAULT NULL,
  `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'admin', '1fedc5a36d03c185065dd2b323886aa5', '2018-07-23', '1');
INSERT INTO `user` VALUES (2, 'test', '7a38c13ec5e9310aed731de58bbc4214', '2018-07-23', '0');

-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role`  (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  INDEX `FKa68196081fvovjhkek5m97n3y`(`role_id`) USING BTREE,
  INDEX `FK859n2jvi8ivhui0rl0esws6o`(`user_id`) USING BTREE
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Fixed;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES (1, 1);
INSERT INTO `user_role` VALUES (2, 2);

SET FOREIGN_KEY_CHECKS = 1;

Dao层

创建一个UserRoleMapper.java

public interface UserRoleMapper extends JpaRepository<User, String> {
    User findByUsername(String username);

}

ShiroConfig

修改ShiroConfig,以让程序支持Shiro的内置注解

/**
     * 开启如下shiro已提供的注解
     * // 表示当前Subject已经通过login进行了身份验证;即Subject.isAuthenticated()返回true。
     * @RequiresAuthentication
     *
     * // 表示当前Subject已经身份验证或者通过记住我登录的。
     * @RequiresUser
     * // 表示当前Subject没有身份验证或通过记住我登录过,即是游客身份。
     * @RequiresGuest
     * // 表示当前Subject需要角色admin和user。
     * @RequiresRoles(value={"admin", "user"}, logical= Logical.AND)
     * // 表示当前Subject需要权限user:a或user:b。
     * @RequiresPermissions (value = { " user : a ", " user : b " }, logical = Logical.OR)
     * @return
     */
    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

UserController

创建一个UserController

@Controller
@RequestMapping("/user")
public class UserController {
    @RequiresPermissions("user:user")
    @RequestMapping("/list")
    public String userList(Model model){
        model.addAttribute("value", "获取用户信息");
        return "user";
    }

    @RequiresPermissions("user:add")
    @RequestMapping("/add")
    public String userAdd(Model model) {
        model.addAttribute("value", "新增用户");
        return "user";
    }

    @RequiresPermissions("user:delete")
    @RequestMapping("/delete")
    public String userDelete(Model model) {
        model.addAttribute("value", "删除用户");
        return "user";
    }
}

主要是为了实现我们的User相关的业务。

LoginController

修改:
添加一个/403的监控

 @GetMapping("/403")
    public String forbid() {
        return "403";
    }

前端页面

前端页面都很简单,直接贴了。
index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<p>你好![<span th:text="${user.username}">username</span>] </p>
<h3>权限测试链接</h3>
<div>
    <a th:href="@{/user/list}">获取用户信息</a>
    <a th:href="@{/user/add}">新增用户</a>
    <a th:href="@{/user/delete}">删除用户</a>
</div>
<a th:href="@{/logout}">注销</a>
</body>
</html>

user.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title th:text="${value}">value</title>
</head>
<body>
<p th:text="${value}">value</p>
<a th:href="@{/index}">返回</a>
</body>
</html>

403.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>暂无权限</title>
</head>
<body>
<p>您没有权限访问该资源!!</p>
<a th:href="@{/index}">返回</a>
</body>

访问测试

直接访问http://localhost:8080 然后登陆帐号密码就可以了。
大概点点里面的链接,看看会发生什么。

总结

1、整体来说,shiro帮我们封装了很多常用的功能,再配合上Jpa,我们甚至不用建表、不用写一行SQL就可以将这个简单功能开发出来。
2、修正一个之前的错误,使用了Druid连接池以后,如果没有做配置,程序是不会帮我们自动创建数据表的。所以在配置文件中加入:

spring.jpa.hibernate.ddl-auto=update

最后代码地址:github

  • 评论列表:
  •  访客
     发布于 2018-12-11 13:14:28  回复该评论
  • INSERT INTO `user` VALUES (1, 'admin', '1fedc5a36d03c185065dd2b323886aa5', '2018-07-23', '1');
    请问这个对应的密码是多少? admin123?
    谢谢

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Copyright bcfou.com.Some Rights Reserved.