SpringBoot+Shiro+mybatis整合实战

SpringBoot+Shiro+mybatis整合

1. 使用Springboot版本2.0.4 与shiro的版本

引入springboot和shiro依赖

<?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.smile</groupId>    <artifactId>spring-demo</artifactId>    <version>1.0-SNAPSHOT</version>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.0.4.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <java.version>1.8</java.version>    </properties>    <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>            <scope>test</scope>        </dependency>        <!--常用工具类 -->        <dependency>            <groupId>org.apache.commons</groupId>            <artifactId>commons-lang3</artifactId>        </dependency>        <!-- mysql所需的配置 -->        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>        </dependency>        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-starter</artifactId>            <version>1.3.2</version>        </dependency>        <!--阿里数据库连接池 -->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid-spring-boot-starter</artifactId>            <version>1.1.10</version>        </dependency>        <!-- Redis客户端 -->        <dependency>            <groupId>redis.clients</groupId>            <artifactId>jedis</artifactId>        </dependency>        <!-- 读取资源文件所需的配置 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-configuration-processor</artifactId>            <optional>true</optional>        </dependency>        <!-- 引入thymeleaf模板依赖 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-thymeleaf</artifactId>        </dependency>        <!-- pagehelper 分页插件 -->        <dependency>            <groupId>com.github.pagehelper</groupId>            <artifactId>pagehelper-spring-boot-starter</artifactId>            <version>1.2.5</version>        </dependency>        <!-- 阿里JSON解析器 -->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>1.2.47</version>        </dependency>        <!-- 集成shiro -->        <dependency>            <groupId>org.apache.shiro</groupId>            <artifactId>shiro-spring</artifactId>            <version>1.4.0</version>        </dependency>        <!-- https://mvnrepository.com/artifact/org.crazycake/shiro-redis -->        <dependency>            <groupId>org.crazycake</groupId>            <artifactId>shiro-redis</artifactId>            <version>3.1.0</version>        </dependency>        <!-- 打印SQL语句-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-jpa</artifactId>        </dependency>    </dependencies></project>

2. 添加相应的配置

server:  port: 8183spring:  thymeleaf:    mode: HTML    encoding: utf-8    cache: false  datasource:    driver-class-name: com.mysql.jdbc.Driver    url: jdbc:mysql://192.168.144.128:3306/spring_shiro?serverTimezone=GMT&useUnicode=true&characterEncoding=utf-8&useSSL=true    #url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false    username: root    password: root    type: com.alibaba.druid.pool.DruidDataSource    maxActive: 20    initialSize: 1    maxWait: 60000    poolPreparedStatements: true    maxPoolPreparedStatementPerConnectionSize: 20    minIdle: 1    timeBetweenEvictionRunsMillis: 60000    minEvictableIdleTimeMillis: 300000    validationQuery: select 1 from dual    testWhileIdle: true    testOnBorrow: false  jackson:    time-zone: GMT+8    date-format: yyyy-MM-dd HH:mm:ss  jpa:    database: mysql    show-sql: true#日志级别打印logging:  level:    com.example.demo: debug    org.springframework: WARN    org.spring.springboot.dao: debug# MyBatismybatis:  typeAliasesPackage: com.example.demo  mapperLocations: classpath:mybatis/**/*Mapper.xml  configLocation: classpath:mybatis/mybatis-config.xml# PageHelperpagehelper:  helperDialect: mysql  reasonable: true  supportMethodsArguments: true  params: count=countSql

3. 将相关配置@Bean注入容器

package com.example.demo.config;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.session.mgt.SessionManager;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.crazycake.shiro.RedisCacheManager;import org.crazycake.shiro.RedisManager;import org.crazycake.shiro.RedisSessionDAO;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.util.LinkedHashMap;import java.util.Map;/** * @时间 2019/11/25 17:17 * @作者 liutao * @描述 */@Configurationpublic class ShiroConfig {    /**     * 设置过滤器     * @param securityManager     * @return     */    @Bean    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();        factoryBean.setSecurityManager(securityManager);        // 设置需要进行登录的路径API        factoryBean.setLoginUrl("/pub/need_login");        // 若是使用前后端分离,则不需要进行设置该方法        factoryBean.setSuccessUrl("/");        // 没有进行授权,返回的API        factoryBean.setUnauthorizedUrl("/pub/not_permit");        // 自定义过滤器        Map<String, String> filterMap = new LinkedHashMap<>();        // 设置退出的过滤器        filterMap.put("/logout", "logout");        // 不需要进行授权就可以进行访问,游客都可以进行访问的API        filterMap.put("/pub/**", "anon");        // 需要进行授权才可以进行访问的API接口        filterMap.put("/authc/**", "authc");        // 有对应的角色才可以进行访问        filterMap.put("/admin/**", "roles[admin]");        // 设置最后的拦截器,需要进行授权才可以进行访问        filterMap.put("/**","authc");        factoryBean.setFilterChainDefinitionMap(filterMap);        return factoryBean;    }    /**     * 设置安全管理器     * @return     */    @Bean    public SecurityManager securityManager(){        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();        securityManager.setSessionManager(sessionManager());        securityManager.setRealm(customRealm());        securityManager.setCacheManager(cacheManage());        return securityManager;    }    /**     * 自定义Realm     * @return     */    @Bean    public CustomRealm customRealm(){        CustomRealm customRealm = new CustomRealm();        // 设置密码的加密        customRealm.setCredentialsMatcher(hashedCredentialsMatcher());        return customRealm;    }    /**     * 设置sessionId的管理器 (前后端分离,要进行获取Token)     * @return     */    @Bean    public SessionManager sessionManager(){        CustomSessionManager sessionManager = new CustomSessionManager();        // 设置sessionDAO -- 里面定义了自定义SessionId        sessionManager.setSessionDAO(redisSessionDAO());        return sessionManager;    }    /**     * 设置密码加密     * @return     */    @Bean    public HashedCredentialsMatcher hashedCredentialsMatcher(){        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();        // 密码算法        matcher.setHashAlgorithmName("md5");        // 加密散列次数        matcher.setHashIterations(3);        return matcher;    }    /**     * 将会话SessionId保存到Redis里面,可以提高性能     * @return     */    public RedisSessionDAO redisSessionDAO(){        RedisSessionDAO dao = new RedisSessionDAO();        dao.setRedisManager(redisManager());        dao.setSessionIdGenerator(new CustomSessionIdGenerator());        return dao;    }    /**     * 接入Redis数据库     * @return     */    public RedisManager redisManager(){        RedisManager redisManager = new RedisManager();        redisManager.setHost("127.0.0.1");        redisManager.setPort(6379);        return redisManager;    }    /**     * 缓存管理     * @return     */    @Bean    public RedisCacheManager cacheManage(){        RedisCacheManager cacheManager = new RedisCacheManager();        cacheManager.setRedisManager(redisManager());        // 设置过期时间,单位是秒        cacheManager.setExpire(60);        return cacheManager;    }    /**     * 加入请求头  前后端分离     * @return     */    @Bean    public WebMvcConfigurer webMvcConfigurer(){        return new WebMvcConfig();    }}

4.创建CustomRealm类继承AuthorizingRealm,实现用户登录认证和权限鉴权

package com.example.demo.config;import com.example.demo.entity.User;import com.example.demo.service.UserService;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.beans.factory.annotation.Autowired;/** * @时间 2019/11/25 17:17 * @作者 liutao * @描述 */public class CustomRealm extends AuthorizingRealm {    @Autowired    private UserService userService;    /**     * 鉴权     * @param principals     * @return     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        String name = (String) principals.getPrimaryPrincipal();
    //若是使用Redis和cache,获取信息转成用户对象
    // User user= (User) principals.getPrimaryPrincipal();
    return null;    }    /**     * 登录认证     * @param token     * @return     * @throws AuthenticationException     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {        String name = (String) token.getPrincipal();        User user = userService.selectUserByName(name);        if(user == null){            return null;        }     // 若是加入Redis和Cache缓存的管理的话,需要返回 用户对象     //new SimpleAuthenticationInfo(user,user.getPassword(),getName());
    return new SimpleAuthenticationInfo(name,user.getPassword(),getName());    }}

5. 创建CustomSessionManager继承DefaultWebSessionManager,可以进行实现Token,进行重写

package com.example.demo.config;import org.apache.shiro.web.servlet.ShiroHttpServletRequest;import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;import org.apache.shiro.web.util.WebUtils;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.Serializable;/** * @时间 2019/11/25 17:18 * @作者 liutao * @描述 */public class CustomSessionManager extends DefaultWebSessionManager {    private static final String AUTHORIZATION = "token";    public CustomSessionManager(){        super();    }    @Override    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {        String sessionId = WebUtils.toHttp(request).getHeader(AUTHORIZATION);        if(sessionId != null){            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,                    ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);            //automatically mark it valid here.  If it is invalid, the            //onUnknownSession method below will be invoked and we'll remove the attribute at that time.            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);            return sessionId;        }else{            return super.getSessionId(request,response);        }    }}

6. 实现自定义SessionId,创建CustomSessionIdGenerator类实现 SessionIdGenerator

package com.example.demo.config;import org.apache.shiro.session.Session;import org.apache.shiro.session.mgt.eis.SessionIdGenerator;import java.io.Serializable;import java.util.UUID;/** * @时间 2019/11/26 16:30 * @作者 liutao * @描述 */public class CustomSessionIdGenerator implements SessionIdGenerator {    private final String PREFIX_SESSIONID = "cc0504";    public CustomSessionIdGenerator(){        super();    }    @Override    public Serializable generateId(Session session) {        return PREFIX_SESSIONID + UUID.randomUUID().toString().replaceAll("-","");    }}

7.前后端分离,在Header里面加入相应的数据信息

package com.example.demo.config;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * @时间 2019/11/25 19:27 * @作者 liutao * @描述 */public class WebMvcConfig implements WebMvcConfigurer {    @Override    public void addCorsMappings(CorsRegistry registry) {        registry.addMapping("/**")                .allowedOrigins("*")  //可访问ip,ip最好从配置文件中获取,                .allowedMethods("PUT", "DELETE","GET","POST")                .allowedHeaders("*")                .exposedHeaders("access-control-allow-headers","access-control-allow-methods","access-control-allow-origin", "access-control-max-age","X-Frame-Options")                .allowCredentials(false).maxAge(3600);    }}

8. mybatis的配置

# MyBatismybatis:  typeAliasesPackage: com.example.demo  mapperLocations: classpath:mybatis/**/*Mapper.xml  configLocation: classpath:mybatis/mybatis-config.xml

mybatis-config.xml中的内容:

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration>        <settings>        <setting name="cacheEnabled"             value="true" />  <!-- 全局映射器启用缓存 -->        <setting name="useGeneratedKeys"         value="false" />  <!-- 不允许 JDBC 支持自动生成主键 -->        <setting name="defaultExecutorType"      value="REUSE" /> <!-- 配置默认的执行器 -->        <!--<setting name="logImpl"                  value="SLF4J" />--> <!-- 指定 MyBatis 所用日志的具体实现 -->        <setting name="logImpl" value="STDOUT_LOGGING" /> <!-- 在控制台打印SQL语句 -->        <!-- <setting name="mapUnderscoreToCamelCase" value="true"/>  驼峰式命名 -->    </settings>    </configuration>

基础Mapper.xml文件内容

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.demo.mapper.UserMapper">    <resultMap id="userResultMap" type="User">        <result column="id" property="id"/>        <result column="name" property="name"/>        <result column="password" property="password"/>        <result column="salt" property="salt"/>    </resultMap>    <select id="selectAllUsers" resultMap="userResultMap">        select * from sys_user    </select>    <select id="selectUserByName" resultMap="userResultMap">        select * from sys_user where name = #{name}    </select></mapper>
(0)

相关推荐