spring-boot-2.0.3不一样系列之shiro-搭建篇

青石路      2022-04-09     185

关键词:

前言

       上一篇:spring-boot-2.0.3源码篇 - 国际化,讲了如何实现国际化,实际上我工作用的模版引擎是freemaker,而不是thymeleaf,不过原理都是相通的。

       接着上一篇,这一篇我来讲讲spring-boot如何整合工作中用到的一个非常重要的功能:安全,而本文的主角就是一个安全框架:shiro。

       Apache Shiro是Java的一个安全框架。目前,使用Apache Shiro的人也越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security的功能强大,但是在实际工作时可能并不需要那么复杂的东西,所以使用小而简单的Shiro就足够了。对于它俩到底哪个好,这个不必纠结,能更简单的解决项目问题就好了。

摘自开涛兄的《跟我学Shiro》

       本文旨在整合spring-boot与shiro,实现简单的认证功能,shiro的更多使用细节大家可以去阅读《更我学shiro》或者看官方文档

  本文项目地址:spring-boot-shiro

spring-boot整合shiro

       集成mybatis

    Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供,然后通过相应的接口注入给Shiro;既然用户、权限这些信息需要我们自己设计、维护,那么可想而知需要进行数据库表的设计了(具体表结构看后文),既然涉及到数据库的操作,那么我们就先整合mybatis,实现数据库的操作。

    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>

    <groupId>com.lee</groupId>
    <artifactId>spring-boot-shiro</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>

    <dependencies>

        <!-- mybatis相关 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

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

    </dependencies>

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

    配置文件application.yml:

spring:
  #连接池配置
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/spring-boot?useSSL=false&useUnicode=true&characterEncoding=utf-8
      username: root
      password: 123456
      initial-size: 1                     #连接池初始大小
      max-active: 20                      #连接池中最大的活跃连接数
      min-idle: 1                         #连接池中最小的活跃连接数
      max-wait: 60000                     #配置获取连接等待超时的时间
      pool-prepared-statements: true    #打开PSCache,并且指定每个连接上PSCache的大小
      max-pool-prepared-statement-per-connection-size: 20
      validation-query: SELECT 1 FROM DUAL
      validation-query-timeout: 30000
      test-on-borrow: false             #是否在获得连接后检测其可用性
      test-on-return: false             #是否在连接放回连接池后检测其可用性
      test-while-idle: true             #是否在连接空闲一段时间后检测其可用性
#mybatis配置
mybatis:
  type-aliases-package: com.lee.shiro.entity
  #config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml
# pagehelper配置
pagehelper:
  helperDialect: mysql
  #分页合理化,pageNum<=0则查询第一页的记录;pageNum大于总页数,则查询最后一页的记录
  reasonable: true
  supportMethodsArguments: true
  params: count=countSql
View Code

    在数据库spring-boot中新建表tbl_user:

DROP TABLE IF EXISTS `tbl_user`;
CREATE TABLE `tbl_user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `username` varchar(50) NOT NULL COMMENT '名称',
  `password` char(32) NOT NULL COMMENT '密码',
  `salt` char(32) NOT NULL COMMENT '盐,用于加密',
  `state` tinyint(2) NOT NULL DEFAULT '1' COMMENT '状态, 1:可用, 0:不可用',
  `description` varchar(50) DEFAULT '' COMMENT '描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

-- ----------------------------
-- Records of tbl_user
-- ----------------------------
INSERT INTO `tbl_user` VALUES ('1', 'admin', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', '1', 'bing,作者自己');
INSERT INTO `tbl_user` VALUES ('2', 'brucelee', '5d5c735291a524c80c53ff669d2cde1b', '78d92ba9477b3661bc8be4bd2e8dd8c0', '1', '龙的传人');
INSERT INTO `tbl_user` VALUES ('3', 'zhangsan', '5d5c735291a524c80c53ff669d2cde1b', '78d92ba9477b3661bc8be4bd2e8dd8c0', '1', '张三');
INSERT INTO `tbl_user` VALUES ('4', 'lisi', '5d5c735291a524c80c53ff669d2cde1b', '78d92ba9477b3661bc8be4bd2e8dd8c0', '1', '李四');
INSERT INTO `tbl_user` VALUES ('5', 'jiraya', '5d5c735291a524c80c53ff669d2cde1b', '78d92ba9477b3661bc8be4bd2e8dd8c0', '1', '自来也');
View Code

    mapper接口:UserMapper.java

package com.lee.shiro.mapper;

import com.lee.shiro.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface UserMapper {

    /**
     * 根据用户名获取用户
     * @param username
     * @return
     */
    User findUserByUsername(@Param("username") String username);
}
View Code

    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.lee.shiro.mapper.UserMapper">
    <select id="findUserByUsername" resultType="User">
        SELECT
            id,username,password,salt,state,description
        FROM
            tbl_user
        WHERE username=#{username}
    </select>
</mapper>
View Code

    service接口:IUserService.java

package com.lee.shiro.service;

import com.lee.shiro.entity.User;

public interface IUserService {

    /**
     * 根据用户名获取用户
     * @param username
     * @return
     */
    User findUserByUsername(String username);
}
View Code

    service实现:UserServiceImpl.java

package com.lee.shiro.service.impl;

import com.lee.shiro.entity.User;
import com.lee.shiro.mapper.UserMapper;
import com.lee.shiro.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User findUserByUsername(String username) {
        User user = userMapper.findUserByUsername(username);
        return user;
    }

}
View Code

    启动类:ShiroApplication.java

package com.lee.shiro;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ShiroApplication {

    public static void main(String[] args) {
        SpringApplication.run(ShiroApplication.class, args);
    }
}
View Code

    测试类:MybatisTest.java

package com.lee.shiro.test;

import com.lee.shiro.ShiroApplication;
import com.lee.shiro.entity.User;
import com.lee.shiro.service.IUserService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ShiroApplication.class)
public class MybatisTest {

    @Autowired
    private IUserService userService;

    @Test
    public void testFindUserByUsername() {
        User user = userService.findUserByUsername("brucelee");
        Assert.assertEquals(user.getDescription(), "龙的传人");
    }
}
View Code

     测试用例顺利通过,则表示mybatis集成成功

       开启logback日志

    其实上面的pom配置已经引入了日志依赖,如图:

    但是你会发现,spring-boot-starter-logging引入了3种类型的日志,你用其中任何一种都能正常打印日志;但是我们需要用3种吗?根本用不到,我们只要用一种即可,至于选用那种,全凭大家自己的喜欢;我了,比较喜欢logback(接触的项目中用的比较多,说白了就是这3种中最熟悉的把);我们来改下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>

    <groupId>com.lee</groupId>
    <artifactId>spring-boot-shiro</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>

    <dependencies>

        <!-- mybatis相关 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- 日志 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
            <exclusions>                    <!-- 剔除spring-boot-starter-logging中的全部依赖 -->
                <exclusion>
                    <groupId>*</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
            <scope>test</scope>             <!-- package或install的时候,spring-boot-starter-logging.jar也不会打进去 -->
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </dependency>

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

    </dependencies>

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

        logback.xml:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
  <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
  <property name="LOG_HOME" value="/log" />
  <!-- 控制台输出 -->
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <pattern>%d{yyyy-MM-dd HH:mm:ss} |%logger| |%level|%msg%n</pattern>
    </encoder>
  </appender>
  <!-- 按照每天生成日志文件 -->
  <appender name="FILE"
            class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <!--日志文件输出的文件名 -->
      <FileNamePattern>${LOG_HOME}/spring-boot-shiro.log.%d{yyyy-MM-dd}.log</FileNamePattern>
      <!--日志文件保留天数 -->
      <MaxHistory>30</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
      <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 -->
      <查看详情  

spring-boot-2.0.3之redis缓存实现,不是你想的那样哦

前言  开心一刻    小白问小明:“你前面有一个5米深的坑,里面没有水,如果你跳进去后该怎样出来了?”小明:“躺着出来呗,还能怎么出来?”小白:“为什么躺着出来?”小明:“5米深的坑,还没有水,跳下去... 查看详情

spring-boot-2.0.3源码篇-filter的注册,值得一看

前言  开心一刻    过年女婿来岳父家走亲戚,当时小舅子主就问:姐夫,你什么时候能给我姐幸福,让我姐好好享受生活的美好。你们这辈子不准备买一套大点的房子吗?姐夫说:现在没钱啊!不过我有一个美丽可爱的... 查看详情

spring-boot-2.0.3源码篇-filter的注册,值得一看

前言  开心一刻    过年女婿来岳父家走亲戚,当时小舅子主就问:姐夫,你什么时候能给我姐幸福,让我姐好好享受生活的美好。你们这辈子不准备买一套大点的房子吗?姐夫说:现在没钱啊!不过我有一个美丽可爱的... 查看详情

intellijidea2017版spring-boot2.0.3邮件发送搭建,概念梳理

邮件发送功能总结    第一部分 背景 一、使用场景(1)注册验证  注册各大网站,通常需要输入邮件地址,在注册成功后,会发送一封邮箱验证的邮件,点击确认,证明这个邮箱是用户自己的(2)... 查看详情

intellijidea2017版spring-boot2.0.3邮件发送搭建,概念梳理

第二部分 邮件发送历史 一、第一封邮件 1、1969年10月,世界上的第一封电子邮件  1969年10月世界上的第一封电子邮件是由计算机科学家LeonardK.教授发给他的同事的一条简短消息。第一条网上信息就是‘LO’,意... 查看详情

不一样的视角来学习spring源码之aop---中

不一样的视角来学习Spring源码之AOP---中cglib代理进阶模拟cglib代理收获💡cglib避免反射调用收获💡系列文章:不一样的视角来学习Spring源码之容器与Bean—上不一样的视角来学习Spring源码之容器与Bean—下不一样的视角来学习... 查看详情

不容易系列之——考新郎(代码片段)

...",具体的操作是这样的:首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排;然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个.最后,揭开盖头,如果找错了对象就要当众跪搓衣板...看来做... 查看详情

kotlin小悟-这个继承有点不一样(代码片段)

今天聊聊kotlin中关于构造函数的一个话题。我们知道,在kotlin中构造函数分为主构造函数和从构造函数,关于详细的内容,可以点击下面的文章链接了解。Kotlin系列之主构造方法和初始化语句块Kotlin系列之从构造方法... 查看详情

e-不容易系列之――考新郎错排数公式

...操作是这样的:  首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排; 然后,让各位新郎寻找自己的新娘.每人只准找一个,并且不允许多人找一个. 最后,揭开盖头,如果找错了对象就要当众跪搓衣... 查看详情

不一样的office365之——使用delve查看热门文档

  我们来谈谈Office365里另外一个很少有人关注的组价,Delve。这个系列的主旨之前也提到过,不是说有多技术,而是要让更多的朋友了解Office365里一些平时没太关注过的组件。这些组件可能会对我们的工作和生活产生很大... 查看详情

学习系列之数据类型

...各样,整数、小数、字符串、字符等等,它们都类型是不一样的,所以你要想在计算机中使用这些类型,就必须在内存中为它申请一块合适的空间。  数据类型总结起来有以下几点:  (1)C程序是一组 查看详情

shiro实战系列之配置

                                 Sh 查看详情

centos命令行系列之centos查看磁盘空间大小(代码片段)

df-h扩展:1.查看当前文件夹所有文件大小du-sh2.查看指定文件下所有文件大小du-h/data/3.查看指定文件大小du-hinstall.log4.查指定文件夹大小du-sh/data  查看详情

scala入门系列:面向对象之trait

...无论继承还是trait,统一都是extends关键字。Scala跟Java8前一样不支持对类进行多继承,但是支持多重继承trait,使用with关键字即可traitHelloTrait{defsayHello(name:String)}traitMakeFriends{defmakeFriends 查看详情

hadoop系列之hbase环境搭建和使用

HBase环境准备HBase下载地址:http://archive.apache.org/dist/hbase/tar-zxvfhbase-1.4.11-bin.tar.gz#解压hbasevim/etc/profile#配置hbase环境变量在最后加上exportPATH=$PATH:/usr/local/soft/hbase-1.4.11/binsource/etc/profile#重启,使hbase生效chown-Rhadoophbase-1.4.1... 查看详情

mybatis入门系列三之类型转换器

...是第三点要求经常会出现java类型和数据库的存储类型不一样,例如java类型是String,数据库中存储的是char、varchar、te 查看详情

shell脚本之笔记一

... ./test.sh,而不是 test.sh运行其它二进制的程序也一样,直接写test.sh    linux系统会去PATH里寻找有没有叫test.sh的,而只有/bin,/sbin,/usr/bin,/usr/sbin等在PATH里,你的当前目    录通常不在PATH里,所以写成test.sh是会... 查看详情