当前位置: 移动技术网 > 科技>操作系统>windows > SpringBoot+Shiro+mybatis整合实战

SpringBoot+Shiro+mybatis整合实战

2019年12月24日  | 移动技术网科技  | 我要评论

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: 8183

spring:
  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

# mybatis
mybatis:
  typealiasespackage: com.example.demo
  mapperlocations: classpath:mybatis/**/*mapper.xml
  configlocation: classpath:mybatis/mybatis-config.xml

# pagehelper
pagehelper:
  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
 * @描述
 */
@configuration
public 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的配置

# mybatis
mybatis:
  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 configuration
public "-//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 mapper
public "-//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>

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网