• SpringBoot整合Shiro、Mybatis、Thymeleaf


    SpringBoot整合Shiro、Mybatis、Thymeleaf

    SpringBoot整合Shiro

    • 新建一个SpringBoot项目导入Thymeleaf依赖

      <dependency>
          <groupId>org.thymeleafgroupId>
          <artifactId>thymeleaf-spring5artifactId>
      dependency>
      <dependency>
          <groupId>org.thymeleaf.extrasgroupId>
          <artifactId>thymeleaf-extras-java8timeartifactId>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 导入SpringBoot整合Shiro依赖

      <dependency>
          <groupId>org.apache.shirogroupId>
          <artifactId>shiro-springartifactId>
          <version>1.4.1version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    • 创建首页以及Controller

      package com.cjp.controller;
      
      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.stereotype.Controller;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.RequestMapping;
      
      @Controller
      public class MyController {
      
          @RequestMapping({"/","/index"})
          public String toIndex(Model model){
              model.addAttribute("msg","hello,shiro");
              return "index";
          }
      
          @RequestMapping("/user/add")
          public String add(){
              return "user/add";
          }
      
          @RequestMapping("/user/update")
          public String update(){
              return "user/update";
          }
      
          @RequestMapping("/toLogin")
          public String toLogin(){
              return "login";
          }
      
          @RequestMapping("/login")
          public String login(String username,String password,Model model){
              //获取当前用户
              Subject subject = SecurityUtils.getSubject();
              //封装用户登录数据
              UsernamePasswordToken token = new UsernamePasswordToken(username,password);
              try {
                  subject.login(token);   //执行登录方法,如果没有异常就ok了
                  return "index";
              }catch (UnknownAccountException e){  //用户名不存在
                  model.addAttribute("msg","用户名不存在");
                  return "login";
              }catch (IncorrectCredentialsException e){//密码不存在
                  model.addAttribute("msg","用户名或密码错误");
                  return "login";
              }
      
          }
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
    • 新建配置ShiroConfig

      package com.cjp.config;
      
      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;
      
      @Configuration
      public class ShiroConfig {
          //ShiroFilterFactoryBean 3
          @Bean
          public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager defaultWebSecurityManager){
              ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
              //设置安全管理器
              bean.setSecurityManager(defaultWebSecurityManager);
      
              //添加内置过滤器
              Map<String, String> filterMap = new LinkedHashMap<>();
              //登陆拦截
              filterMap.put("/user/*","authc");
              bean.setFilterChainDefinitionMap(filterMap);
              bean.setLoginUrl("/toLogin");
              return bean;
          }
      
          //DefaultWebSecurityManager  2
          @Bean(name = "manager")
          public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
              DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
              //关联UserRealm
              manager.setRealm(userRealm);
              return manager;
          }
      
          //创建Realm对象,  需要自定义  1
          @Bean
          public UserRealm userRealm(){
              UserRealm userRealm = new UserRealm();
              return userRealm;
          }
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
    • 自定义Realm对象:UserRealm

      package com.cjp.config;
      
      
      import org.apache.shiro.authc.*;
      import org.apache.shiro.authz.AuthorizationInfo;
      import org.apache.shiro.realm.AuthorizingRealm;
      import org.apache.shiro.subject.PrincipalCollection;
      
      //自定义的Realm
      public class UserRealm extends AuthorizingRealm {
          //授权
          @Override
          protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
              return null;
          }
      
          //认证
          @Override
          protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
              String username = "cjp";
              String password = "123";
              UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
      
              if (!usernamePasswordToken.getUsername().equals(username)){ //用户名认证
                  return null;   //抛出错误
              }
      
              return new SimpleAuthenticationInfo("",password,"");
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31

    项目结构:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GRyV694o-1659748359609)(D:\Desktop\暑假学习笔记\imag\image-20220805150601569.png)]

    整合Mybatis、连接数据库、整合thymeleaf

    • 导入Mybatis,连接数据库的依赖

      <dependency>
          <groupId>com.github.theborakompanionigroupId>
          <artifactId>thymeleaf-extras-shiroartifactId>
          <version>2.1.0version>
      dependency>
      <dependency>
          <groupId>mysqlgroupId>
          <artifactId>mysql-connector-javaartifactId>
      dependency>
      <dependency>
          <groupId>org.mybatis.spring.bootgroupId>
          <artifactId>mybatis-spring-bootartifactId>
          <version>2.1.1version>
      dependency>
      <dependency>
          <groupId>log4jgroupId>
          <artifactId>log4jartifactId>
          <version>1.2.17version>
      dependency>
      <dependency>
          <groupId>com.alibabagroupId>
          <artifactId>druidartifactId>
          <version>1.1.21version>
      dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    • 配置数据库连接

      spring:
        datasource:
          username: root
          password: 123456
          url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.alibaba.druid.pool.DruidDataSource
          #Spring Boot 默认是不注入这些属性值的,需要自己绑定
          #druid 数据源专有配置
          initialSize: 5
          minIdle: 5
          maxActive: 20
          maxWait: 60000
          timeBetweenEvictionRunsMillis: 60000
          minEvictableIdleTimeMillis: 300000
          validationQuery: SELECT 1 FROM DUAL
          testWhileIdle: true
          testOnBorrow: false
          testOnReturn: false
          poolPreparedStatements: true
      
          #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
          #如果允许时报错  java.lang.ClassNotFoundException: org.apache.log4j.Priority
          #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
          filters: stat,wall,log4j
          maxPoolPreparedStatementPerConnectionSize: 20
          useGlobalDataSourceStat: true
          connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
    • 创建实例类 User、对应的UserMapper、UserMapper.xml、UserService、UserServiceImpl

      User:

      package com.cjp.pojo;
      
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      
      @Data
      @AllArgsConstructor
      @NoArgsConstructor
      public class User {
          private int id;
          private String name;
          private String pwd;
          private String perms;
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

      UserMapper.xml:

      
      DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      <mapper namespace="com.cjp.mapper.UserMapper">
          <select id="queryUserByName" resultType="User" parameterType="String">
              select * from user where name = #{name}
          select>
      mapper>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      UserService:

      package com.cjp.service;
      
      import com.cjp.pojo.User;
      
      public interface UserService {
          public User queryUserByName(String name);
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      UserServiceImpl:

      package com.cjp.service;
      
      import com.cjp.mapper.UserMapper;
      import com.cjp.pojo.User;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Service;
      
      @Service
      public class UserServiceImpl implements UserService{
      
          @Autowired
          UserMapper userMapper;
          @Override
          public User queryUserByName(String name) {
              User user = userMapper.queryUserByName(name);
              return user;
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

      配置文件中绑定:

      mybatis.type-aliases-package=com.cjp.pojo
      mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
      
      • 1
      • 2
    • 修改UserRealm:

      package com.cjp.config;
      
      
      import com.cjp.pojo.User;
      import com.cjp.service.UserServiceImpl;
      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.session.Session;
      import org.apache.shiro.subject.PrincipalCollection;
      import org.apache.shiro.subject.Subject;
      import org.springframework.beans.factory.annotation.Autowired;
      
      //自定义的Realm
      public class UserRealm extends AuthorizingRealm {
      
          @Autowired
          UserServiceImpl userService;
          //授权
          @Override
          protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
              System.out.println("======>授权");
              SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
              //拿到当前登录的用户对象
              Subject subject = SecurityUtils.getSubject();
              User currentUser = (User) subject.getPrincipal();//拿到user对象
              //设置当前用户权限
              info.addStringPermission(currentUser.getPerms());
      
              return info;
          }
      
          //认证
          @Override
          protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
              System.out.println("=======>认证");
              UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
              User user = userService.queryUserByName(usernamePasswordToken.getUsername());
              if (user==null){ //用户名认证
                  return null;   //抛出错误
              }
              Subject subject = SecurityUtils.getSubject();
              Session session = subject.getSession();
              session.setAttribute("userSession",user);
              return new SimpleAuthenticationInfo(user,user.getPwd(),"");
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
    • 修改ShiroConfig:

      package com.cjp.config;
      
      import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
      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;
      
      @Configuration
      public class ShiroConfig {
          //ShiroFilterFactoryBean 3
          @Bean
          public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("manager") DefaultWebSecurityManager defaultWebSecurityManager){
              ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
              //设置安全管理器
              bean.setSecurityManager(defaultWebSecurityManager);
      
              //添加内置过滤器  拦截
              Map<String, String> filterMap = new LinkedHashMap<>();
              //授权
              filterMap.put("/user/add","perms[user:add]");
              filterMap.put("/user/update","perms[user:update]");
              //登陆拦截
              filterMap.put("/user/*","authc");
              bean.setFilterChainDefinitionMap(filterMap);
              bean.setLoginUrl("/toLogin");
              //设置未授权页面
              bean.setUnauthorizedUrl("/unauth");
              return bean;
          }
      
          //DefaultWebSecurityManager  2
          @Bean(name = "manager")
          public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
              DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
              //关联UserRealm
              manager.setRealm(userRealm);
              return manager;
          }
      
          //创建Realm对象,  需要自定义  1
          @Bean
          public UserRealm userRealm(){
              UserRealm userRealm = new UserRealm();
              return userRealm;
          }
      
          //整合ShiroDialect:用来整合Shiro thymeleaf
          @Bean
          public ShiroDialect getshiroDialect(){
              return new ShiroDialect();
          }
      
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
    • 页面权限展示设置 导入shiro命名空间

      <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
      
      • 1
    • index.html

      DOCTYPE html>
      <html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
      <head>
          <meta charset="UTF-8">
          <title>首页title>
      head>
      <body>
      <h1>首页h1>
      <p th:text="${msg}">p>
      <hr>
      <div shiro:hasPermission="user:add">
          <a th:href="@{/user/add}">添加a>
      div>
      <div shiro:hasPermission="user:update">
          <a th:href="@{/user/update}">修改a>
      div>
      br>
      <div th:if="${session.userSession}==null">
          <a th:href="@{/toLogin}">登录a>
      div>
      body>
      html>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
    • 项目结构

    在这里插入图片描述

  • 相关阅读:
    Leetcode——岛屿的最大面积
    Android在XML和代码中,同时设置背景,导致背景叠加的问题
    【网络编程】一文带你搞懂HTTPS协议
    (附源码)springboot码头作业管理系统 毕业设计 341654
    Linux—curl 命令用法大总结
    OpenCV-Python学习(3)—— OpenCV 图像色彩空间转换
    ECCV 2022 | MaxViT: Multi-Axis Vision Transformer
    条件控制
    2022杭电多校 第6场 1008.Shinobu Loves Segment Tree 规律题
    HashMap在JDK1.7中多线程并发会出现死循环,超详细图解
  • 原文地址:https://blog.csdn.net/m0_47801930/article/details/126189359