Spring Boot整合Shiro完成认证,权限管理,MD5+salt加密

Spring Boot整合Shiro完成认证,权限管理,MD5+salt加密

整合代码如下

Pom.xml
<?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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.junwei</groupId>
    <artifactId>springboot-shiro</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-shiro</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.28</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <!--thymel对shiro的扩展标签 整合-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

后端代码
  1. User.java

    package com.junwei.springbootshiro.pojo;
    
    import lombok.*;
    import org.springframework.stereotype.Repository;
    
    /**
     * @Auther: wangjunwei
     * @Description: 用户实体类
     * @Date: Created in 16:18 2019/6/8
     */
    @Setter
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    @ToString
    @Repository
    public class User {
        private int id;
        private String username;
        private String password;
        private String perms;
    }
    
  2. UserMapper.java

    package com.junwei.springbootshiro.mapper;
    
    import com.junwei.springbootshiro.pojo.User;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    
    /**
     * @Auther: wangjunwei
     * @Description: 用户mapper层
     * @Date: Created in 16:19 2019/6/8
     */
    @Mapper
    public interface UserMapper {
        User findUser(@Param("username") String username);
        User findById(@Param("id") Integer id);
    
        void toRegist(@Param("user") User user,@Param("perms") String perms);
    }
    
  3. UserMapper.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.junwei.springbootshiro.mapper.UserMapper">
        <insert id="toRegist">
            insert into user (username, password,perms) values (#{user.username},#{user.password},
                                                                #{perms})
        </insert>
        <select id="findUser" resultType="com.junwei.springbootshiro.pojo.User">
            select id,username,password from user where username = #{username}
        </select>
        <select id="findById" resultType="com.junwei.springbootshiro.pojo.User">
            select id,username,password,perms from user where id=#{id}
        </select>
    </mapper>
    
  4. UserService.java

    package com.junwei.springbootshiro.service;
    
    import com.junwei.springbootshiro.mapper.UserMapper;
    import com.junwei.springbootshiro.pojo.User;
    import com.junwei.springbootshiro.utils.Salt;
    import org.apache.shiro.crypto.hash.Md5Hash;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    /**
     * @Auther: wangjunwei
     * @Description: 用户业务逻辑层
     * @Date: Created in 16:21 2019/6/8
     */
    @Service
    public class UserService {
        @Autowired
        private UserMapper userMapper;
    
        public User findUser(String username) {
            return userMapper.findUser(username);
        }
    
        public User findById(Integer id) {
            return userMapper.findById(id);
        }
    
        public void toRegist(User user) {
            //密码加盐
            user.setPassword(new Md5Hash(user.getPassword(), Salt.addSalt).toString());
            userMapper.toRegist(user,"user:none");
        }
    }
    
  5. ShiroConfig.java

    package com.junwei.springbootshiro.shiro;
    
    import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
    import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    /**
     * @Auther: wangjunwei
     * @Description: Shiro配置类
     * @Date: Created in 10:34 2019/6/8
     */
    @Configuration
    public class ShiroConfig {
    
        /**
         * @param defaultWebSecurityManager 1
         * @return : org.apache.shiro.spring.web.ShiroFilterFactoryBean
         * @Author: wangjunwei
         * @Date: Created in 10:57 2019/6/8
         * @Description: 创建ShiroFilterFactoryBean
         */
        @Bean(name = "shiroFilterFactoryBean")
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager"
        ) DefaultWebSecurityManager defaultWebSecurityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
            //添加shiro内置过滤器
            /*
                annon:表示可以匿名使用
                authc:表示需要认证(登录)才能使用,没有参数
                roles:参数可以写多个,多个时必须加上双引号,并且参数之间用逗号分隔
                    例如/admins/user/**=perms["user:add:*,
                    user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
                rest:根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。
                port:当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,
                其中schmal是协议http或https等,serverName是你访问的host,
                8081是url配置里port的端口,queryString是你访问的url里的?后面的参数。
                authcBasic:没有参数表示httpBasic认证
                ssl:表示安全的url请求,协议为https
                user:当登入操作时不做检查
                perms:该资源必须授予权限才可以访问
             */
    
            Map<String, String> fMap = new LinkedHashMap<>();
            //拦截页面
            fMap.put("/add", "authc");
            fMap.put("/update", "authc");
    
            //授权过滤器
            //注意:当前授权拦截后,shiro会自动跳转到未授权页面
            fMap.put("/add", "perms[user:add]");
            fMap.put("/update", "perms[user:update]");
    
            shiroFilterFactoryBean.setFilterChainDefinitionMap(fMap);
    
            //被拦截返回登录页面
            shiroFilterFactoryBean.setLoginUrl("/login");
            //设置未授权提示页面
            shiroFilterFactoryBean.setUnauthorizedUrl("/permission");
            return shiroFilterFactoryBean;
        }
    
        /**
         * @param userRealm 1
         * @return : org.apache.shiro.web.mgt.DefaultWebSecurityManager
         * @Author: wangjunwei
         * @Date: Created in 17:24 2019/6/14
         * @Description: 创建SecurityManager
         */
        @Bean(name = "defaultWebSecurityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
            DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
            //关联Realm
            defaultWebSecurityManager.setRealm(userRealm);
            return defaultWebSecurityManager;
        }
    
        /**
         * @return : com.junwei.springbootshiro.shiro.UserRealm
         * @Author: wangjunwei
         * @Date: Created in 16:55 2019/6/14
         * @Description: 创建Realm
         * 并设置加密规则
         */
        @Bean(name = "userRealm")
        public UserRealm getRealm(@Qualifier("hashedCredentialsMatcher") HashedCredentialsMatcher hashedCredentialsMatcher) {
            UserRealm userRealm = new UserRealm();
            userRealm.setCredentialsMatcher(hashedCredentialsMatcher);
            return userRealm;
        }
    
        /**
         * @return : at.pollux.thymeleaf.shiro.dialect.ShiroDialect
         * @Author: wangjunwei
         * @Date: Created in 18:00 2019/6/15
         * @Description: 配置ShiroDialect,用于thymeleaf和shiro标签配合使用
         */
        @Bean
        public ShiroDialect getShiroDialect() {
            return new ShiroDialect();
        }
    
        /**
         * @return : org.apache.shiro.authc.credential.HashedCredentialsMatcher
         * @Author: wangjunwei
         * @Date: Created in 19:14 2019/6/15
         * @Description: 设置加密对象,加密规则
         */
        @Bean(name = "hashedCredentialsMatcher")
        public HashedCredentialsMatcher hashedCredentialsMatcher() {
            HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
            //使用md5加密算法进行加密
            hashedCredentialsMatcher.setHashAlgorithmName("md5");
            //设置散列次数:加密次数
            hashedCredentialsMatcher.setHashIterations(1);
            return hashedCredentialsMatcher;
        }
    }
    
  6. UserRealm.java

    package com.junwei.springbootshiro.shiro;
    
    import com.fasterxml.jackson.annotation.JsonTypeInfo;
    import com.junwei.springbootshiro.pojo.User;
    import com.junwei.springbootshiro.service.UserService;
    import com.junwei.springbootshiro.utils.Salt;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.util.ByteSource;
    import org.springframework.beans.factory.annotation.Autowired;
    
    /**
     * @Auther: wangjunwei
     * @Description: 自定义Realm
     * @Date: Created in 16:17 2019/6/8
     */
    public class UserRealm extends AuthorizingRealm {
        @Autowired
        private UserService userService;
    
        /**
         * @param principalCollection 1
         * @return : org.apache.shiro.authz.AuthorizationInfo
         * @Author: wangjunwei
         * @Date: Created in 16:53 2019/6/14
         * @Description: 执行授权
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            //授权
            System.out.println("授权");
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //到数据库查询当前登录用户的授权字符串
            //获取当前登录用户
            Subject subject = SecurityUtils.getSubject();
            User user = (User) subject.getPrincipal();
            User result = userService.findById(user.getId());
            //授权
            simpleAuthorizationInfo.addStringPermission(result.getPerms());
            return simpleAuthorizationInfo;
        }
    
        /**
         * @param authenticationToken 1
         * @return : org.apache.shiro.authc.AuthenticationInfo
         * @Author: wangjunwei
         * @Date: Created in 16:54 2019/6/14
         * @Description: 执行认证
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            System.out.println("认证");
            //shiro判断逻辑 判断用户名和密码
            UsernamePasswordToken user = (UsernamePasswordToken) authenticationToken;
            User newUser = userService.findUser(user.getUsername());
            if (newUser == null) {
                return null;
            }
            System.out.println(user.getPassword());
            //加密加盐认证
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(newUser,
                    newUser.getPassword(),
                    ByteSource.Util.bytes(Salt.addSalt), getName());
            return authenticationInfo;
        }
    }
    
  7. Salt.java

    package com.junwei.springbootshiro.utils;
    
    /**
     * @Auther: wangjunwei
     * @Description: 用户加盐
     * @Date: Created in 18:51 2019/6/15
     */
    public class Salt {
        public static final String addSalt = "regist@^$*#!";
    }
    
  8. PageController.java

    package com.junwei.springbootshiro.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    /**
     * @Auther: wangjunwei
     * @Description: 页面跳转controller
     * @Date: Created in 17:38 2019/6/14
     */
    @Controller
    public class PageController {
        @RequestMapping("/")
        public String toIndex(){
            return "index";
        }
    
        @RequestMapping("/{pageName}")
        public String toPage(@PathVariable String pageName){
            return pageName;
        }
    }
    
  9. UserController.java

    package com.junwei.springbootshiro.controller;
    
    import com.junwei.springbootshiro.pojo.User;
    import com.junwei.springbootshiro.service.UserService;
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    
    /**
     * @Auther: wangjunwei
     * @Description: 用户controller层
     * @Date: Created in 16:23 2019/6/8
     */
    @Controller
    public class UserController {
        @Autowired
        private UserService userService;
    
        @RequestMapping(value = "toLogin",method = RequestMethod.POST)
        public String toLogin(User user, Model model){
            //shiro用户认证
            Subject subject = SecurityUtils.getSubject();
            //封装用户数据
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),
                    user.getPassword());
            try {
                subject.login(token);
                model.addAttribute("username",user.getUsername());
                return "index";
            }catch (UnknownAccountException e){
                model.addAttribute("msg","用户名不存在");
                return "login";
            }catch (IncorrectCredentialsException e){
                model.addAttribute("msg","密码错误");
                return "login";
            }
        }
    
        /**
         * @Author: wangjunwei
         * @Date: Created in 18:42 2019/6/15
         * @Description:
         * 注销功能
         * @return : java.lang.String
         */
        @RequestMapping("logout")
        public String logout(){
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
            return "index";
        }
    
        /**
         * @Author: wangjunwei
         * @Date: Created in 18:46 2019/6/15
         * @Description: 用户注册
         * @param user 1
         * @return : java.lang.String
         */
        @RequestMapping(value = "toRegist",method = RequestMethod.POST)
        public String toRegist(User user){
            userService.toRegist(user);
            return "index";
        }
    }
    
配置文件application.properties
#spring集成Mybatis环境 别名扫描
mybatis.type-aliases-package=com.junwei.springbootshiro.pojo
#加载Mybatis配置文件
mybatis.mapper-locations = classpath:mapper/*Mapper.xml
spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/yjlg?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = 123
前台代码
  1. index.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:shiro="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
    <h1>首页</h1>
    <!--验证当前用户是否为“访客”,即未登录的用户-->
    <p shiro:guest=""><a href="/login">请登录</a></p>
    <p><a href="/regist">注册</a></p>
    <p shiro:authenticated="">你好,
        <shiro:principal property="username" /><br/><a href="/logout">注销</a></p>
    <a shiro:hasPermission="user:add" href="/add">添加</a>
    <a shiro:hasPermission="user:update" href="/update">修改</a>
    </body>
    </html>
    
  2. login.html

    <!DOCTYPE html>
    <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="UTF-8">
        <title>登录页面</title>
    </head>
    <body>
    <h1>登录页面</h1>
    <form action="/toLogin" method="post">
        <p>
            <span>用户名:</span>
            <input type="text" name="username">
        </p>
        <p>
            <span>密码:</span>
            <input type="password" name="password">
        </p>
        <input type="submit" value="登陆">
    </form>
    <h3 th:text="${msg}"></h3>
    </body>
    </html>
    
  3. regist.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户注册</title>
    </head>
    <body>
    <h1>用户注册</h1>
    <form action="/toRegist" method="post">
        <p>用户名:<input type="text" name="username"></p>
        <p>密码:<input type="password" name="password"></p>
        <input type="submit" value="注册">
    </form>
    </body>
    </html>
    
  4. add.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户添加</title>
    </head>
    <body>
        <h1>用户添加页面</h1>
    </body>
    </html>
    
  5. update.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户修改</title>
    </head>
    <body>
    <h1>用户修改页面</h1>
    </body>
    </html>
    
  6. premission.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>未授权提示页面</title>
    </head>
    <body>
    <h1>为授权提示页面</h1>
    </body>
    </html>
    
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值