Spring boot基础学习之(十八):通过shiro框架使用Mybatis实现用户的认证完整的认证流程

news2024/11/17 16:04:58

在上几篇文章的基础上,实现本次案例

注意:本篇文章的实现代码在几篇文章都已经详细的讲过了,所以在此篇文章,将不再有理论知识的陈述,更过的流程,如何通过代码实现连接数据库进行认证

添加本次案例所需要的依赖

完整代码依赖: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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
        <relativePath/>
    </parent>
    <groupId>com.springboot_shiro</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>14</java.version>
    </properties>
<!--    web环境依赖-->
    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
<!--        thymeleaf依赖实现数据的传递-->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-java8time</artifactId>
        </dependency>
<!--        导入shiro与spring的集成-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.10.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

先通过idea app连接数据库idea 工具Database连接MySQL数据库

连接数据库的内容在前几篇文章都演示过了,这一篇文章则是前几篇文章的整合版,将前几篇的内容整合在一起,更好的适合我们的使用

在数据库创建一个表,存放着我们登录时验证的信息

 连接数据库:数据源为Druid:application.yml

spring:
  datasource:
    username: demo1
    password: 123
    url: jdbc:mysql://localhost:3306/girls?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
    type: com.alibaba.druid.pool.DruidDataSource
    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
    driver-class-name: com.mysql.cj.jdbc.Driver

连接成功后

创建pojo类,用以存放数据库的信息user.java


@Data
@AllArgsConstructor
@NoArgsConstructor
public class user {
    private String username;
    private String password;
}

创建mapper接口,定义数据库的具体操作,查询操作 interence UserMapper 



@Repository
@Mapper
public interface UserMapper {
    public user queryUser(String name);
}

创建service层

创建userService 内容与UserMapper 接口差不多,少了注解:此接口为了更好的了解

package com.springboot_shiro.service;

import com.springboot_shiro.pojo.user;

public interface userService {
    public user queryUser(String name);
}

创建userService接口的实现类:


import javax.annotation.Resource;

@Service
public class userServiceimp implements userService {
    @Autowired
    UserMapper userMapper;


    @Override
    public user queryUser(String name) {
        System.out.println("22");
        return userMapper.queryUser(name);
    }
}

创建Mapper配置文件,执行sql语句

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--        映射到指定的接口-->
<mapper namespace="com.springboot_shiro.mapper.UserMapper">
    <!--    并重载接口中定义的方法-->
    <select id="queryUser" resultType="user" parameterType="String">
        select * from girls.login where username = #{name}
    </select>

</mapper>

这里的id值为前面创建的userMapper方法,在这个配置文件执行前面的配置的方法

光通过一个id属性是没办法让xml文件知道,这里的方法那个接口中的方法,我们要用过配置文件去设置路径


mybatis.type-aliases-package=com.springboot_shiro.pojo
mybatis.mapper-locations=classpath:/mapper/*.xml

通过测试文件看能否输出从数据库中查询的数据

@SpringBootTest
class DemoApplicationTests {

    @Autowired
    com.springboot_shiro.service.userServiceimp userServiceimp;

    @Test
    void contextLoads() throws  Exception{
        System.out.println(userServiceimp.queryUser("demo1"));
    }

}

控制台输出:

数据查询成功:与数据库的交互完成

将mybatis与shiro框架整合在一起

shiro框架

域名配置


@Controller
public class controller1 {
    //索引网页的设置
    @RequestMapping("/")
    public String Toindex(Model model){
        return "index";
    }
    //add网页
    @RequestMapping("/add")
    public String add(){
        return "add";
    }
    //update网页
    @RequestMapping("/update")
    public String update(){
        return "update";
    }
    //登录界面
    @RequestMapping("/tologin")
    public String login(){
        return "login";
    }
    //登录界面form表格进行提交,提交到这
    @RequestMapping("/get")
    public String getword(String username,String password,Model model){
        //组件一:subject
        Subject subject = SecurityUtils.getSubject();
        //将用用户名和密码进行加密
        UsernamePasswordToken Token = new UsernamePasswordToken(username, password);
        //通过subject将Token交给securitymanager进行验证
        try {
            subject.login(Token);      //验证通过,跳转到index网页
            return "index";
        }
        catch (UnknownAccountException e){     //出现用户名错误
            model.addAttribute("msg","用户名输入错误");  //通过model类进参数的传递
            return "login";
        }
        catch (IncorrectCredentialsException e){ //出现密码错误
            model.addAttribute("msg","密码输入错误");
            return "login";
        }

    }
}

定义shiro验证流程

package com.springboot_shiro.Myconfig;

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;
//isAuthenticated:用于判断用户是否已经进行登录
@Configuration
public class config1 {
        //定义认证流程过程中需要的程序
//    shiroFilterFactoryBean组件可以实现指定网页的拦截,并为文件的访问设置权限
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager FactoryBean){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(FactoryBean);
        //拦截请求
        Map<String,String> map = new LinkedHashMap<>();
        //权限设置:当访问/add这个网页要先进行登录
        map.put("/add","authc");
        //访问/update则不需要进行任何操作,直接可以进行访问
        map.put("/update","anon");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        //访问需要进行认证的网页,如果没有进行登录则进行网页的跳转
        shiroFilterFactoryBean.setLoginUrl("/tologin");
        return shiroFilterFactoryBean;
    }
    //对内部的组件进行管理
    @Bean
    public DefaultWebSecurityManager securityManager(@Qualifier("realm") Realm realm){
        DefaultWebSecurityManager SecurityManager = new DefaultWebSecurityManager();
        SecurityManager.setRealm(realm);
        return SecurityManager;
    }

    //用户验证的桥梁,实现用户的认证信息的确认
    @Bean
    public Realm realm(){
        return new Realm();
    }
}

前面的代码与上一篇文章相同,不需要进行更改,

但Realm则不同,他要与前面关于Mybatis配置结合在一起



public class Realm extends AuthorizingRealm {
    @Autowired
    com.springboot_shiro.service.userService userService;

    //授权内容则是在这个接口进行配置
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了授权");
        return null;
    }


    //验证则是在这个接口进行配置
    //获取subject传递来的参数加密的令牌Token,进行认证
    //AuthenticationInfo是一个接口:return它的的实现类

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken Token) throws AuthenticationException {

        UsernamePasswordToken token =(UsernamePasswordToken) Token;  //转换
        user user = userService.queryUser(token.getUsername());
        System.out.println(token.getUsername());
        if (user==null){
            return null;
        }
        //密码的验证,在spring boot架构中给一个类SimpleAuthenticationInfo可以自动化进行认证
        return new SimpleAuthenticationInfo("",user.getPassword(),"");
    }
}

代码完毕:执行项目进行登录

控制台输出:说明登陆成功

 

尝试登陆其他的用户:报错

 shiro与mybatis关于认证方面整合完成

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419661.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【并发编程】ConcurrentHashMap源码分析(二)

addCount 统计元素个数 private transient volatile long baseCount; //初始化大小为2,如果竞争激烈,会扩容 2->4 private transient volatile CounterCell[] counterCells;如果竞争不激烈的情况下&#xff0c;直接用cas (baseCount1)如果竞争激烈的情况下&#xff0c;采用…

项目管理的三要素:时间、成本和质量

项目管理的三要素&#xff1a;时间、成本和质量&#xff0c;他们作为衡量一个项目的成功失败的指标&#xff0c;贯穿项目整个过程。 时间&#xff1a; 项目时间管理包括使项目按时完成必须实施的各项过程。 项目计划按照逻辑关系安排计划活动顺序时&#xff0c;需要考虑进度…

C#,码海拾贝(16)——求行列式值的全选主元高斯消去法,《C#数值计算算法编程》源代码升级改进版

1 高斯消去法 数学上&#xff0c;高斯消元法&#xff08;或译&#xff1a;高斯消去法&#xff09;&#xff0c;是线性代数规划中的一个算法&#xff0c;可用来为线性方程组求解。但其算法十分复杂&#xff0c;不常用于加减消元法&#xff0c;求出矩阵的秩&#xff0c;以及求出…

利好消息不断原油价格大幅走高

​几个OPEC成员国将在年底前将全球产量再削减116万桶/天&#xff0c;这将进一步给央行遏制全球通胀的努力带来负担&#xff0c;但关键是保护该联盟更广泛的产量策略免受政治压力的影响。 华盛顿介入批评了上周日的声明&#xff0c;8个OPEC生产国&#xff08;包括组织的领导国沙…

Java中jar包的创建和使用

Java中jar包的创建和使用 jar包的基本概念 jar包的全称是java archive。jar包本质就是一种压缩包。在Java开发中一般是用来压缩类的一个包。类似C/C中的静态库和动态库&#xff0c;但是又不完全是。 C/C中的静态库和动态库是对中间文件&#xff08;*.o&#xff09;打包成一个…

【电路原理】电路元件基本知识详解

博主简介&#xff1a;努力学习的22级计科生一枚~博主主页&#xff1a; 是瑶瑶子啦所属专栏: 电路理论 前言1.电阻元件2.电容元件3.电感元件4.独立电源4.1&#xff1a;电压源4.2&#xff1a;电流源5.受控电源6.符号补充&#xff1a;7.总结本专栏文章主要总结、归纳电路原理、电路…

数据结构-排序(2)

前言&#xff1a; 上一章节介绍了 排序中的插入排序和选择排序&#xff0c; 分别复盘了插入排序中的直接插入排序和希尔排序以及选择排序中的选择排序和堆排序。今天继续复盘交换排序。 目录 2.3交换排序 2.3.1冒泡排序 2.3.2快速排序 2.3.2快速排序非递归 2.3交换排序 基…

HTML5 <figure> 标签、HTML5 <footer> 标签

HTML5 <figure> 标签 实例 使用 <figure> 元素标记文档中的一个图像&#xff1a; <figure><img src"img_pulpit.jpg" alt"The Pulpit Rock" width"304" height"228"> </figure>尝试一下 浏览器支持 …

在proteus中仿真arduino实现矩阵键盘程序

矩阵键盘是可以解决我们端口缺乏的问题&#xff0c;当然&#xff0c;如果我们使用芯片来实现矩阵键盘的输入端口缺乏的问题将更加划算了&#xff0c;本文暂时不使用芯片来解决问题&#xff0c;而使用纯朴的8根线来实现矩阵键盘&#xff0c;目的是使初学者掌握原理。想了解使用芯…

Lua脚本

目录说明什么是Lua脚本为什么要使用Lua脚本Lua脚本的安装Lua脚本的使用Lua的变量Lua脚本的算术运算符Lua脚本的关系运算符Lua脚本的逻辑运算符Lua脚本不同的操作Lua脚本的函数和标准库Redis整合Lua脚本&#xff08;重点&#xff09;在Java集成Lua在SpringBoot项目中使用Redis集…

前端PC端适配,网页端适配

问题背景 由于我司是使用的大屏&#xff0c;且设计稿尺寸为19201080。但是需要适配各种分辨率&#xff0c; 比如12801024(5:4)、1366768(16&#xff1a;10)、16801050&#xff08;16&#xff1a;10&#xff09;。在尝试了多种方法之后&#xff0c;最终确定主要的适配方法为rem…

【vue3】04-vue基础语法补充及阶段案例

文章目录vue基础语法补充vue的computedvue的watch侦听书籍购物车案例vue基础语法补充 vue的computed computed&#xff1a;用于声明要在组件实例上暴露的计算属性。&#xff08;官方文档描述&#xff09; 我们已经知道&#xff0c;在模板中可以直接通过插值语法显示一些data中…

科学的演变:从笛卡尔到生成式人工智能

编者按&#xff1a;本文主要介绍了科学的演变历史&#xff0c;从笛卡尔到生成式人工智能。文章探讨了数学在验证科学原理中的作用&#xff0c;并介绍了新机器学习工具如何验证新的科学。 文中提到&#xff0c;将生成式人工智能与Excel或iPhone进行比较是低估了这一新技术的潜在…

【AI】PaddlePaddle实现自动语音识别

文章目录文档背景安装环境Python版本pip环境安装模型需要的环境项目目录结构数据准备生成数据字典数据预处理训练模型创建模型构建模型的目的模型黑盒在模型中充当什么角色解码方法总结文档背景 学习AI的过程中&#xff0c;难免会出现各种各样的问题。比如&#xff0c;什么样的…

制造业生产管理系统(500强制造企业数字化实践)

前言 制造业是国民经济的支柱产业之一&#xff0c;随着科技和数字化的发展&#xff0c;制造业正在经历着一场新的变革。传统的制造模式已经无法满足市场的快速变化和客户的多样化需求&#xff0c;制造企业急需通过数字化和智能化转型升级&#xff0c;提高生产效率和质量水平&a…

第十四届蓝桥杯嵌入式详解

目录 第一部分 客观试题&#xff08;15 分&#xff09; 不定项选择&#xff08;1.5 分/题&#xff09; 第二部分 程序设计试题&#xff08;85 分&#xff09; 2.1 STM32CubeMX初始化配置 2.1.1 配置GPIO 2.1.2 配置ADC 2.1.3 配置RCC 2.1.4 配置定时器TIM 2.1.5 配置ADC1、AD…

【从零开始学Skynet】基础篇(二):了解Skynet

1、节点和服务 在下图所示的服务端系统中&#xff0c;每个Skynet进程&#xff08;操作系统进程&#xff09;都称为一个节点&#xff0c;每个节点都可以开启数千个Lua服务&#xff0c;每个服务都是一个Actor。不同节点可以部署在不同的物理机上&#xff0c;提供分布式集群的能力…

Velocity入门到精通(上篇)

最近自己所做的项目使用到这个Velocity模板引擎&#xff0c;分享一下在互联网找的学习资料。 目录 一. velocity简介 1. velocity简介 2. 应用场景 3. velocity 组成结构 二. 快速入门 1. 需求分析 2. 步骤分析 3. 代码实现 3.1 创建maven工程 3.2 引入坐标 3.3 编…

Redis锁的租约问题

目录Redis的租约问题Redis租约问题的想法Redis租约问题的解决方案Redis的租约问题 首先我们先来说一说什么是Redis的租约问题。   在我们实现Redis分布式锁的时候&#xff0c;我们会出现Redis锁的时间<业务执行执行时间&#xff0c;这其实就是一个典型的租约问题&#xf…

【C++】你了解命名空间吗?

C语言之父&#xff1a;Bjarne Stroustrup博士(本贾尼) 当我们在编写代码的时候&#xff0c;可能会产生一些命名冲突&#xff0c;为了解决这一冲突我们引出命名空间的概念 (ps:命名冲突的产生主要包括两个方面原因&#xff1a;1、与库函数名冲突&#xff1b;2、相互之间的冲突&…