Springboot整合shiro实现权限控制框架完整版,复制即用

1、开发环境:

1、mysql - 5.7
2、navicat(mysql客户端管理工具)
3、idea 2017.2
4、jdk8
5、tomcat 8.5
6、springboot2.0.3
7、mybatis 3
8、shiro1.4
9、maven3.3.9

2.数据库设计

在这里插入图片描述

3.目录结构

在这里插入图片描述

3.1pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wo</groupId>
    <artifactId>shiro_springboot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--shiro的包-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

</project>

3.2application.yml

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/qf?useUnicode=true&characterEncoding=utf8&useSSL=false
mybatis:
  mapper-locations: classpath:mapper/*Mapper.xml

3.3实体类

1.TbSysUser

@Data
public class TbSysUser {


    private Integer userid;

    private String loginName;

    private String password;
}

2.TbSysPermissions


@Data
public class TbSysPermissions {

    private Integer permissionId;

    private String perName;
}

3.4 dao

1.TbUserDao

@Mapper
public interface TbUserDao {

    TbSysUser login(@Param("loginName") String loginName);
}

2.TbSysPermissionDao

@Mapper
public interface TbSysPermissionDao {

    List<TbSysPermissions> findPermissonByLoginName(@Param("loginName") String loginName);
}

3.5mapper

1.TbUserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wo.dao.TbUserDao">
    <resultMap id="BaseResult" type="com.wo.pojo.TbSysUser">

        <id property="userid" column="userid"></id>
        <result property="loginName" column="login_name"></result>
        <result property="password" column="password"></result>
    </resultMap>

    <select id="login" resultMap="BaseResult">
        select * from tb_sys_user where login_name = #{loginName}
    </select>
</mapper>

2.TbPermissionMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wo.dao.TbSysPermissionDao">
    <resultMap id="BaseResult" type="com.wo.pojo.TbSysPermissions">

        <id property="permissionId" column="permission_id"></id>
        <result property="perName" column="per_name"></result>
    </resultMap>

    <select id="findPermissonByLoginName" resultMap="BaseResult">
        SELECT sp.per_name from tb_sys_user su,tb_sys_role sr,tb_sys_permission sp, tb_user_role ur,tb_role_permission rp
        where su.userid=ur.user_id
        and ur.role_id = sr.role_id
        and sr.role_id = rp.role_id
        and rp.permission_id = sp.permission_id
        and su.login_name=#{loginName};
    </select>
</mapper>

3.6 ShiroConfig

package com.wo.config;

@Configuration
public class ShiroConfig {

    //1.获取到我们的myrealm
    @Bean(name = "myRealm")
    public MyRealm myRealm(@Qualifier("hashedCredentialsMatcher")HashedCredentialsMatcher matcher){
        MyRealm myRealm = new MyRealm();
        myRealm.setAuthorizationCachingEnabled(false);
        myRealm.setCredentialsMatcher(matcher);
        return myRealm;
    }

    //2.声明securityManager
    @Bean(name = "defaultWebSecurityManager")
    public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm){
        //shiro核心
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        //在核心中设置我们自定义的realm
        defaultWebSecurityManager.setRealm(myRealm);

        return defaultWebSecurityManager;

    }

    //3.工厂
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        //权限
        //声明没有权限的情况下走的接口名称
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
//        //告诉shiro有用什么权限可以访问什么接口
        //如果不加注解不加map,默认没有权限控制
//         Map map = new HashMap<>();
//         map.put("/findAll","perms[user_findAll]");
//         map.put("/deleteById","perms[user_delete]");
//        //将访问接口的权限放置到shiroFileter中
//         shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;

    }

    //使用aop注解模式来使用权限
    //使用aop扫描包含shiro注解的类
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }
    //将WebSecurityManager 交给spring aop来进行管理
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
        return authorizationAttributeSourceAdvisor;
    }

    /**
     * 密码校验规则HashedCredentialsMatcher
     * 这个类是为了对密码进行编码的 ,
     * 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
     * 这个类也负责对form里输入的密码进行编码
     * 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
     */
    @Bean("hashedCredentialsMatcher")
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //指定加密方式为MD5
        credentialsMatcher.setHashAlgorithmName("MD5");
        //加密次数
        credentialsMatcher.setHashIterations(1);
        credentialsMatcher.setStoredCredentialsHexEncoded(true);
        return credentialsMatcher;
    }

}

3.7 MyRealm

@Component
public class MyRealm extends AuthorizingRealm {

    @Autowired
    TbUserDao tbUserDao;

    @Autowired
    TbSysPermissionDao tbSysPermissionDao;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        //获取到前端传输用户名
        String username = (String) principalCollection.getPrimaryPrincipal();
        //使用用户名查询该用户的权限
        List<TbSysPermissions> permissonByLoginName = tbSysPermissionDao.findPermissonByLoginName(username);
        //声明set进行去重
        HashSet<String> set=new HashSet<>();
        for (TbSysPermissions tb:permissonByLoginName) {
            set.add(tb.getPerName());
        }
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setStringPermissions(set);
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获得到用户名
        String username = (String) authenticationToken.getPrincipal();
        //使用用户名查询密码
        TbSysUser user = tbUserDao.login(username);
        //不使用加盐加密
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, user.getPassword(), getName());
        //使用加盐加密
        //SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, user.getPassword(),ByteSource.Util.bytes("wang"), getName());
        return simpleAuthenticationInfo;
    }
}

3.8 controller

1.UserController

@Controller
public class UserController {

    @RequestMapping("/tologin")
    public String tologin(){
        return "login";
    }
    
    @RequestMapping("/login")
    public String login(TbSysUser tbSysUser){
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(tbSysUser.getLoginName(), tbSysUser.getPassword());
        try {
            subject.login(token);

        }catch (IncorrectCredentialsException ini){
            System.out.println(ini.getMessage());
        }
        if (subject.isAuthenticated()){
            return "redirect:findAll";
        }else{
            return "login";
        }
    }

    @RequestMapping("/logout")
    public String logout(){
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return "login";
    }
    @RequiresPermissions(value = {"user_findAll"})
    @RequestMapping("/findAll")
    public String findALL(){
        return "index";
    }
    @RequiresPermissions(value = {"user_deletesss"})
    @RequestMapping("/deleteById")
    public String deleteById(){

        return "index";
    }


    @RequestMapping("/unauth")
    public String unauth(){
        return "unauth";
    }
}

2.PermissionExcepitonController

//控制器增强  异常捕获类
@ControllerAdvice
public class PermissionExcepitonController {
    //告诉控制器 捕捉什么类型的异常 以及对异常进行处理
    @ExceptionHandler(value = AuthorizationException.class)
    public String excepiton(){
        return "unauth";
    }
    @ExceptionHandler(value = ArithmeticException.class)
    public String urithmeticException(){
        return "error";
    }
}

3.9 启动类

@SpringBootApplication
public class ShiroSpringBootApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShiroSpringBootApplication.class);
    }
}

4.templates页面

4.1 error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>您当前的操作有误,请稍后再试</h1>
</body>
</html>

4.2 index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>用户登录成功</h1>

<a href="/logout">退出登录</a>
</body>
</html>

4.3 login.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/login" method="post">
        用户名:<input type="text" name="loginName"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="提交">
    </form>
</body>
</html>

4.4 unauth.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>您没有权限,请联系管理员</h1>
</body>
</html>

5.TestMD5加密

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestMD5 {



    @Test
    public void getMD5PassWord(){

        String hashAlgorithName = "MD5";//加密算法
        String password = "123";//登陆时的密码
        int hashIterations =1;//加密次数
        ByteSource credentialsSalt = ByteSource.Util.bytes("admin");//使用登录名做为salt
        SimpleHash simpleHash = new SimpleHash(hashAlgorithName, password, credentialsSalt, hashIterations);
        System.out.println(simpleHash);
    }

}

6.测试

1.登录
在这里插入图片描述

2.登录admn账户,该账户有findAll权限,但是没有delete权限
在这里插入图片描述
在这里插入图片描述

7.附数据库语句,有数据



SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `tb_role_permission`
-- ----------------------------
DROP TABLE IF EXISTS `tb_role_permission`;
CREATE TABLE `tb_role_permission` (
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

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

-- ----------------------------
-- Table structure for `tb_sys_permission`
-- ----------------------------
DROP TABLE IF EXISTS `tb_sys_permission`;
CREATE TABLE `tb_sys_permission` (
  `permission_id` int(11) NOT NULL AUTO_INCREMENT,
  `per_name` varchar(255) DEFAULT NULL,
  `menu_name` varchar(255) DEFAULT NULL,
  `menu_type` varchar(255) DEFAULT NULL,
  `menu_url` varchar(255) DEFAULT NULL,
  `menu_code` varchar(255) DEFAULT NULL,
  `parent_code` varchar(255) DEFAULT NULL,
  `per_desc` varchar(255) DEFAULT NULL,
  `if_vilid` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`permission_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_sys_permission
-- ----------------------------
INSERT INTO `tb_sys_permission` VALUES ('1', 'user_findAll', null, null, null, null, null, null, null);
INSERT INTO `tb_sys_permission` VALUES ('2', 'user_delete', null, null, null, null, null, null, null);
INSERT INTO `tb_sys_permission` VALUES ('3', 'user_update', null, null, null, null, null, null, null);

-- ----------------------------
-- Table structure for `tb_sys_role`
-- ----------------------------
DROP TABLE IF EXISTS `tb_sys_role`;
CREATE TABLE `tb_sys_role` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(255) DEFAULT NULL,
  `role_deso` varchar(255) DEFAULT NULL,
  `if_vilid` tinyint(4) DEFAULT NULL,
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_sys_role
-- ----------------------------
INSERT INTO `tb_sys_role` VALUES ('1', '普通会员', '查询', null);
INSERT INTO `tb_sys_role` VALUES ('2', '管理员', '查询和删除', null);
INSERT INTO `tb_sys_role` VALUES ('3', '超级管理员', '查询删除新增或更新', null);

-- ----------------------------
-- Table structure for `tb_sys_user`
-- ----------------------------
DROP TABLE IF EXISTS `tb_sys_user`;
CREATE TABLE `tb_sys_user` (
  `userid` int(11) NOT NULL AUTO_INCREMENT,
  `login_name` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `state` tinyint(4) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `realname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`userid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_sys_user
-- ----------------------------
INSERT INTO `tb_sys_user` VALUES ('1', 'normal111', '202cb962ac59075b964b07152d234b70', '1', '2019-07-05 11:17:03', 'zhangsan');
INSERT INTO `tb_sys_user` VALUES ('2', 'normal222', '202cb962ac59075b964b07152d234b70', '1', '2020-09-18 19:57:43', 'lisi');
INSERT INTO `tb_sys_user` VALUES ('3', 'admin', '202cb962ac59075b964b07152d234b70', '1', '2020-09-17 19:58:34', 'wangwu');
INSERT INTO `tb_sys_user` VALUES ('4', 'root', '202cb962ac59075b964b07152d234b70', '1', '2020-09-24 19:58:50', 'zhangfei');

-- ----------------------------
-- Table structure for `tb_user_role`
-- ----------------------------
DROP TABLE IF EXISTS `tb_user_role`;
CREATE TABLE `tb_user_role` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tb_user_role
-- ----------------------------
INSERT INTO `tb_user_role` VALUES ('1', '1');
INSERT INTO `tb_user_role` VALUES ('2', '1');
INSERT INTO `tb_user_role` VALUES ('3', '2');
INSERT INTO `tb_user_role` VALUES ('4', '3');

©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页