Springboot+shiro+md5(配置类配置)

筅森魡賤 提交于 2020-12-16 12:53:57

一.导入依赖包

<!--spring boot 默认lettuce连接redis的技术-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!--邮件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <!--jdbc依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <!--前端模板引擎依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!--springmvc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web-services</artifactId>
        </dependency>

        <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>

        <!--热部署依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--mysql数据库依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--简化实体类依赖(set/get)-->
        <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>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>

        <!-- SpringBoot - MyBatis 逆向工程 -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.2</version>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!--EXCEL-->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.1</version>
        </dependency>

        <dependency>
            <groupId>net.oschina.likaixuan</groupId>
            <artifactId>excelutil</artifactId>
            <version>2.0.2</version>
        </dependency>

        <!--对象池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <!--连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.0</version>
        </dependency>

        <!-- fastjson阿里巴巴jSON处理器 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.13</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.4.0</version>
        </dependency>

        <!--thymeleaf对shiro扩展的依赖-->
        <dependency>
            <groupId>com.github.theborakompanioni</groupId>
            <artifactId>thymeleaf-extras-shiro</artifactId>
            <version>2.0.0</version>
        </dependency>

        <!--jedis依赖包-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

        <!--redisson-->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.5.4</version>
        </dependency>

        <!-- shiro+redis缓存插件 -->
        <dependency>
            <groupId>org.crazycake</groupId>
            <artifactId>shiro-redis</artifactId>
            <version>2.4.2.1-RELEASE</version>
        </dependency>

       <!-- 整合jsp所需依赖,要是添加了thymeleaf似乎会出问题-->
        <!--<dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
        </dependency>-->

        <!--jstl-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
View Code

二.添加配置

#tomcat启动端口
server.port=9090
#server.servlet.context-path=/

#自动重启
spring.devtools.restart.enabled=true
#添加额外监听的路径
#spring.devtools.restart.additional-paths=src/main/
#添加忽略目录(排除的路径)
#spring.devtools.restart.exclude=/excludepath/

#实时刷新(通知浏览器实时刷新,要下插件)
spring.devtools.livereload.enabled=true

#mysql配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://xx.xx.xx.xx:3306/xxx?useUnicode=true&characterEncoding=utf8
spring.datasource.username = xxx
spring.datasource.password = xxxx
spring.datasource.max-active=20
spring.datasource.max-idle=8
spring.datasource.min-idle=8
spring.datasource.initial-size=10

#mybatis
#把数据库字段的下划线转换成实体类中的驼峰式命名
mybatis.configuration.map-underscore-to-camel-case=true

#mybatis表映射文件目录
mybatis.mapper-locations=classpath:mapper/*.xml

#springmvc
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp


#配置分页插件pagehelper
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params.count=countSql

#禁用thymeleaf缓存
spring.thymeleaf.cache=false


#配置连接池
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#druid监控配置
spring.datasource.filters=stat,wall,log4j
spring.datasource.dbcp2.min-idle=5
#初始化提供的连接数
spring.datasource.dbcp2.initial-size=5
#最大的连接数
spring.datasource.dbcp2.max-total=5
#等待连接获取的最大超时时间
spring.datasource.dbcp2.max-wait-millis=200




##rabbitMQ
#spring.rabbitmq.host=xx.xx.xx.xx
#spring.rabbitmq.port=5672
#spring.rabbitmq.username=user
#spring.rabbitmq.password=user

##redis
#spring.redis.host=xx.xx.xx.xx
#spring.redis.port=6379
#spring.redis.password=xxx
#spring.redis.timeout=1000ms
##lettuce最大连接数
#spring.redis.lettuce.pool.max-active=8
##连接池最大阻塞时间(-1表示没有限制
#spring.redis.lettuce.pool.max-wait=-1ms
##最大空闲连接
#spring.redis.lettuce.pool.max-idle=8
##最小空闲连接
#spring.redis.lettuce.pool.min-idle=0
#
#logging.level.com.seecen=debug
View Code

由于springboot还没集成shiro的properties所以要添加配置类,配置类如下(添加配置类之前最好先自定义Realm)

自定义Realm

package com.taotao.shiro;

import com.taotao.pojo.User;
import com.taotao.service.UserService;
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.crypto.hash.Md5Hash;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

/**
 * Author: TaoTao  2019/9/14
 */
@Component
public class UserRealm  extends AuthorizingRealm {
    private static Logger logger = LoggerFactory.getLogger(UserRealm.class);
    @Autowired
    private UserService userService;

    /**
     * 验证身份信息
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        /**
         * 验证用户名步骤
         * 1.获取令牌中的用户名
         * 2.根据用户名去查询是否有该用户
         *      a.有用户存在
         *      b.没有,直接抛出异常
         * 3.返回一个验证用户名和密码的类对象(封装了md5加密的验证方式)
         */
        logger.info("---------------- 执行 Shiro 凭证认证 ----------------------");
        String name = (String) token.getPrincipal();
        // 从数据库获取对应用户名密码的用户
        User userInfo = userService.findUserByNames(name);
        if (userInfo != null) {
            // 用户为禁用状态
            if (userInfo.getuState() != 0) {
                throw new DisabledAccountException("账户已被禁用!");
            }
            logger.info("---------------- Shiro 凭证认证成功 ----------------------");
            //md5加密再加盐
            //根据表单数据和加密字符串和盐值进行比较验证
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    name, //用户
                    userInfo.getuPwd(), //密码
                    ByteSource.Util.bytes(userInfo.getuSal()),//盐值
                    getName()  //realm name
            );
            // 返回给安全管理器,由 securityManager 比对密码的正确性
            return authenticationInfo;
        }
        throw new UnknownAccountException();
    }

    /**
     * 获取操作权限
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info("---------------- 执行 Shiro 权限获取 ---------------------");
        //给资源进行授权
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //到数据库查询当前登录用户的授权字符串
        //获取当前登录用户
        Subject subject = SecurityUtils.getSubject();
        User user = (User) subject.getPrincipal();
//        User dbUser = userService.find
        info.addStringPermission(null);
        logger.info("---------------- Shiro 权限获取成功 ----------------------");
        return info;
      /*  String username = (String) principals.getPrimaryPrincipal();
        //持久化操作:根据用户名获取角色信息和权限信息
        //role: admin manage    perms:user:create user :update  模块:权限
        Set<String> permissionList = new HashSet<>();
        permissionList.add("user:list");
        permissionList.add("user:create");
        permissionList.add("user:update");
        Set<String> roleList = new HashSet<>();
        roleList.add("admin");
        roleList.add("manager");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(roleList);
        authorizationInfo.setStringPermissions(permissionList);
        return authorizationInfo;*/

        }

    }

}

添加配置

package com.taotao.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;

/**
 * Author: TaoTao  2019/9/18
 */
@Configuration
public class ShiroConfig {

    /**
     * Filter工厂
     * @param securityManager
     * @return
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean  = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        Map<String,String> filterMap = new LinkedHashMap<String, String>();
        filterMap.put("/user/login","anon"); //指定路径放行
        filterMap.put("/user/loginVer","anon");

        //设置为登录跳转的页面
        shiroFilterFactoryBean.setLoginUrl("/user/login");
        //设置未授权跳转页面
        shiroFilterFactoryBean.setUnauthorizedUrl("/user/noAuth");
        //授权过滤
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        return shiroFilterFactoryBean;
    }

    /**
     * 密码校验规则HashedCredentialsMatcher
     * 这个类是为了对密码进行编码的 ,
     * 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
     * 这个类也负责对form里输入的密码进行编码
     * 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 使用md5 算法进行加密
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        // 设置散列次数: 加密次数(这个地方没有盐值也不会影响密码对比)
        hashedCredentialsMatcher.setHashIterations(3);
        return hashedCredentialsMatcher;
    }


    /**
     * 自定义Realm
     */
    @Bean(name="userRealms")
    public UserRealm getRealm(){
        UserRealm userRealm = new UserRealm();
        //配置加密方式(不然登录失败)
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userRealm;
    }

    /**
     * 安全管家
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealms") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //关联realm
        securityManager.setRealm(userRealm);
        return securityManager;
    }


    /**
     * 配置ShiroDialect ,用于thymeleaf和shiro标签配合使用
     * @return
     */
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }



}

 

MD5加密加盐

public static void main(String[] args) {
        //第一:把用户的密码通过md5算法加密 
        String password = "uuu";
//        String md5String = new Md5Hash(password).toString();//不可逆加密算法
//        System.out.println("原密码:"+password);
//        System.out.println("md5加密的密码:"+md5String);
//        //注册,保存加密后的值
//        //登录验证  把表单值动态加密再进行比较uuu
//        //第二种:加密同时加点盐
//        md5String = new Md5Hash(password,"abc").toString();
//        System.out.println("md5加密且加盐后的密码:"+md5String);

        //第三种:加密次数 增加破解成本
        String md5String;
        md5String = new Md5Hash("aaa","9734983ae2c939da48d8bc738d34ffb2",3).toString();
        System.out.println("md5加密且加盐,还加加密次数后的密码:"+md5String);

//        //第四种:随机盐值,配合加密次数
////        String sal = getRandomString();
//        md5String = new Md5Hash(password,"abc",3).toString();
//        System.out.println("md5加密且随机颜值,还加加密次数后的密码:"+md5String);

 

总结

在搭建和权限这块基本没什么问题,我所出现的问题是,将密码加密存入数据库后,用户登入失败,在查询资料后发现没有添加 HashedCredentialsMatcher 配置,

然后一直在纠结数据库中的密码使用了盐值进行加密,然后HashedCredentialsMatcher 中并没有添加盐值,而且在该配置类中修改加密次数也可以登入成功(难道这个配置只是在说我加密了哦,求大佬指点)

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!