shiro与Spring Boot 整合

news2024/12/27 12:46:45

目录

框架整合

创建模块

添加依赖 

添加配置文件 

添加启动类

​编辑 

 登录认证实现

后端接口服务实现

实现前端页面  


框架整合

创建模块

添加依赖 

    <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.1.RELEASE</version>
        </parent>
        <dependencies>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring-boot-web-starter</artifactId>
                <version>1.9.0</version>
            </dependency>

            <!--mybatis-plus-->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>3.0.5</version>
            </dependency>

            <!--mysql-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.46</version>
            </dependency>

            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
        </dependencies>

添加配置文件 

添加配置文件 application.yml,添加基础配置

mybatis-plus: 
 configuration: 
     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 
 mapper-locations: classpath:mapper/*.xml 

spring: 
 datasource: 
     type: com.zaxxer.hikari.HikariDataSource 
     driver-class-name: com.mysql.jdbc.Driver 
     url: jdbc:mysql://localhost:3306/shirodb?characterEncoding=utf8&useSSL=false
     username: root 
     password: 123123 
 jackson: 
     date-format: yyyy-MM-dd HH:mm:ss
     time-zone: GMT+8 
shiro: 
 loginUrl: /myController/login

添加启动类

@SpringBootApplication 
@MapperScan("com.atguigu.shiro.mapper") 
public class ShiroApplication { 
     public static void main(String[] args) { 
         SpringApplication.run(ShiroApplication.class, args); 
 } 
}

 登录认证实现

访问数据库获取用户信息,实现登录认证

后端接口服务实现

(1)创建库表

CREATE DATABASE IF NOT EXISTS `shirodb` CHARACTER SET utf8mb4; 
USE `shirodb`; 
 
CREATE TABLE `user` ( 
 `id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '编号', 
 `name` VARCHAR(30) DEFAULT NULL COMMENT '用户名', 
 `pwd` VARCHAR(50) DEFAULT NULL COMMENT '密码', 
 `rid` BIGINT(20) DEFAULT NULL COMMENT '角色编号', 
 PRIMARY KEY (`id`)  
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户表'; 

(2)创建实体

@Data 
@NoArgsConstructor 
@AllArgsConstructor 
public class User { 
 private Integer id; 
 private String name; 
 private String pwd; 
 private Integer rid; 
} 

(3)创建 mapper

@Repository 
public interface UserMapper extends BaseMapper<User> { 
} 

(4)创建 service 

创建接口

public interface UserService { 
 //用户登录 
 User getUserInfoByName(String name); 
} 

创建实现类

@Service 
public class UserServiceImpl implements UserService { 
 @Autowired 
 private UserMapper userMapper; 
 
 @Override 
 public User getUserInfoByName(String name) { 
     QueryWrapper<User> wrapper = new QueryWrapper<>(); 
     wrapper.eq("name",name); 
     User user = userMapper.selectOne(wrapper); 
     return user; 
 } 
} 

(5)自定义realm

@Component
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    //自定义授权方法 
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    //自定义登录认证方法 
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //1 获取用户身份信息 
        String name = token.getPrincipal().toString();
        //2 调用业务层获取用户信息(数据库中) 
        User user = userService.getUserInfoByName(name);
        //3 判断并将数据完成封装 
        if (user != null) {
            AuthenticationInfo info = new SimpleAuthenticationInfo(
                    token.getPrincipal(),
                    user.getPwd(),
                    ByteSource.Util.bytes("salt"),
                    token.getPrincipal().toString()
            );
            return info;
        }
        return null;
    }
} 

 (7)实现controller

@Controller
@RequestMapping("myController")
public class MyController {
    @GetMapping("userLogin")
    @ResponseBody
    public String userLogin(String name, String pwd) {
        //1 获取 Subject 对象 
        Subject subject = SecurityUtils.getSubject();
        //2 封装请求数据到 token 对象中 
        AuthenticationToken token = new
                UsernamePasswordToken(name, pwd);
        //3 调用 login 方法进行登录认证 
        try {
            subject.login(token);
            return "登录成功";
        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("登录失败");
            return "登录失败";
        }
    }
} 

 (8)测试

* 确认数据库密码是加盐 3 次加密密码

*启动服务

*通过浏览器访问:http://localhost:8080/myController/userLogin?name=张三&pwd=z3

实现前端页面  

Shiro整合Thymeleaf

添加 login 页面

<!DOCTYPE html> 
<html lang="en"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
</head> 
<body> 
 <h1>Shiro 登录认证</h1> 
 <br> 
 <form action="/myController/userLogin"> 
 <div>用户名:<input type="text" name="name" value=""></div> 
 <div>密码:<input type="password" name="pwd" value=""></div> 
 <div><input type="submit" value="登录"></div> 
 </form> 
 
</body> 
</html>

添加 main 页面

<!DOCTYPE html> 
<html lang="en" xmlns:th="http://www.thymeleaf.org"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
</head> 
<body> 
 
 <h1>Shiro 登录认证后主页面</h1> 
 <br> 
 登录用户为:<span th:text="${session.user}"></span> 
</body> 

添加 controller 方法,改造认证方法

    //跳转登录页面
    @GetMapping("login")
    public String login() {
        return "login";
    }


    //登录认证
    @GetMapping("userLogin")
    public String userLogin(String name, String pwd, HttpSession
            session) {
        //1 获取 Subject 对象 
        Subject subject = SecurityUtils.getSubject();
        //2 封装请求数据到 token 对象中 
        AuthenticationToken token = new UsernamePasswordToken(name, pwd);
        //3 调用 login 方法进行登录认证 
        try {
            subject.login(token);
            session.setAttribute("user", token.getPrincipal().toString());
            return "main";
        } catch (AuthenticationException e) {
            e.printStackTrace();
            System.out.println("登录失败");
            return "登录失败";
        }
    }

修改配置文件

配置类

启动,访问测试 

多个 realm 的认证策略设置

多个realm实现原理

  当应用程序配置多个 Realm 时,例如:用户名密码校验、手机号验证码校验等等。 Shiro 的 ModularRealmAuthenticator 会使用内部的 AuthenticationStrategy 组件判断认 证是成功还是失败。

  AuthenticationStrategy 是一个无状态的组件,它在身份验证尝试中被询问 4 次(这 4 次交互所需的任何必要的状态将被作为方法参数):

(1)在所有 Realm 被调用之前

(2)在调用 Realm 的 getAuthenticationInfo 方法之前

(3)在调用 Realm 的 getAuthenticationInfo 方法之后

(4)在所有 Realm 被调用之后

  认证策略的另外一项工作就是聚合所有 Realm 的结果信息封装至一个 AuthenticationInfo 实例中,并将此信息返回,以此作为 Subject 的身份信息。

Shiro 中定义了 3 种认证策略的实现:

AuthenticationStrategy class 描述

AtLeastOneSuccessfulStrategy ==》只要有一个(或更多)的 Realm 验证成功,那么认证将视为成功

FirstSuccessfulStrategy ==》第一个 Realm 验证成功,整体认证将视为成功,且后续 Realm 将被忽略

AllSuccessfulStrategy==》 所有 Realm 成功,认证才视为成功

ModularRealmAuthenticator 内置的认证策略默认实现是 AtLeastOneSuccessfulStrategy 方式。可以通过配置修改策略

多个realm代码实现

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

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

相关文章

音视频windows安装ffmpeg6.0并使用vs调试源码笔记

建立在上一步&#xff0c;vs已经能够正常调试qt项目&#xff0c;可以实现&#xff1a; 1&#xff1a;qt可以使用mvsc &#xff08;使用cdb&#xff09;进行调试。 2&#xff1a;vs已经可以加载qt项目&#xff0c;借助vs进行调试。 本文目标&#xff1a;编译ffmpeg库&#xf…

chatgpt赋能Python-python3的内置函数

Python3内置函数大全 Python3是一种高级编程语言&#xff0c;拥有丰富的内置函数库。这些内置函数包括许多核心功能和常用操作。在这篇文章中&#xff0c;我们将介绍一些最常用和最有用的Python3内置函数。 1. print() print()函数用于将输出打印到控制台。它是Python中最常…

chatgpt赋能Python-python3怎么换行

Python3中的换行是许多初学者和经验丰富的工程师们都需要掌握的关键概念之一。在本文中&#xff0c;我们将探讨Python3中如何使用换行&#xff0c;包括介绍和结论。 什么是Python3中的换行&#xff1f; 在Python3中&#xff0c;换行是指将一行代码分成多个部分&#xff0c;以…

数据结构-单调栈1

先介绍一下单调栈是什么 一种特别设计的栈结构&#xff0c;为了解决如下的问题&#xff1a; 给定一个可能含有重复值的数组arr&#xff0c;i位置的数一定存在如下两个信息 1&#xff09;arr[i]的左侧离i最近并且小于(或者大于)arr[i]的数在哪&#xff1f; 2&#xff09;arr[…

【天线专题】史密斯(Smith)圆图

对一个器件进行表征时,所发生的反射大小取决于入射信号“看到的”阻抗。由于任何阻抗都能用实部和虚部(R+jX 或 G+jB )表示,故可以将他们绘制在所谓复阻抗平面的直线网络上,如下图所示。遗憾的是,开路(一种常见的射频阻抗)在实轴上表现为无限大,因而无法表示出来。 …

集合Arrary

目录 ArraryList 引用基本类型 案例1&#xff1a;定义一个集合添加学生姓名年龄 案例2&#xff1a;查看是否存在这个id 案例3&#xff1a;手机 案例4&#xff1a;学生管理系统&#xff08;不完整&#xff09; 集合长度可变&#xff1a;自动扩容集合和数据 长度存储数据类…

Riiid Answer Correctness Prediction - lgb baseline 学习

链接 特征 features [user_questions, user_mean, content_questions, content_mean, prior_question_elapsed_time]user_df train[train.answered_correctly ! -1].groupby(user_id).agg({answered_correctly: [count, mean]}).reset_index() user_df.columns [user_id, …

chatgpt赋能Python-python3怎么安装util

如何安装python3的util模块 Python是一种高级编程语言&#xff0c;可用于从网页应用到人工智能的各种应用程序。它具有简单易学的语法和强大的功能&#xff0c;而且其可扩展性也非常好。 然而&#xff0c;要使用Python的所有功能&#xff0c;需要具有各种库和模块的支持。本文…

【设计模式】单例模式(创建型)

一、前言 学习设计模式我们关注的是什么&#xff0c;如何实现么&#xff1f;是也不是。我认为比了解如何实现设计模式更重要的是这些设计模式的应用场景&#xff0c;什么场景下我们该用这种设计模式&#xff1b;以及这些设计模式所包含的思想&#xff0c;最终帮助我们把代码写…

DNS正反向解析- 的基本实现步骤和报错解决过程

先copy一张图提升一下理解 DNS解析过程如图分为以下三种过程&#xff1a;首先是DNS客户机解析器&#xff0c;从WEB浏览器中输入相应URL&#xff0c;DNS客户机解析器会首先检查自己本地host文件是否存在网站映射关系&#xff0c;成功则直接完成域名解析。如果host中没有相关映射…

Java学习路线(3)——基础数据类型操作

一、自动类型转换 1、什么是自动类型转换&#xff1f; 自动类型转化是范围小的数据可赋值给范围大的数据且精度不损失&#xff0c;且可以跨越式转化。 基础数据类型之间的转换如下&#xff1a; byte(1)—short(2)—char(2)—int(4)—long(8)—float(4)—double(8) 2、表达式的…

cs109-energy+哈佛大学能源探索项目 Part-2.1(Data Wrangling)

博主前期相关的博客见下&#xff1a; cs109-energy哈佛大学能源探索项目 Part-1&#xff08;项目背景&#xff09; 这次主要讲数据的整理。 Data Wrangling 数据整理 在哈佛的一些大型建筑中&#xff0c;有三种类型的能源消耗&#xff0c;电力&#xff0c;冷冻水和蒸汽。 冷冻…

求二进制位中一的个数

原题链接&#xff1a;牛客网 题目内容&#xff1a; 写一个函数返回参数二进制中 1 的个数&#xff0c;负数使用补码表示。 比如&#xff1a; 15 0000 1111 4 个 1 方法一&#xff1a; #include<stdio.h>int NumberOf1(unsigned int n) {int count 0;while (n)…

分布式事务常见解决方案

分布式事务常见解决方案 一、事务介绍 事务是一系列的动作&#xff0c;它们综合在一起才是一个完的工作单元&#xff0c;这些动作必须全部完成&#xff0c;如果有一个失败的话&#xff0c;那么事务就会回滚到最开始的状态&#xff0c;仿佛什么都没发生过一样。 1、单事务概念…

通过关键字搜索接口获取alibaba国际站商品列表

作为一名技术爱好者&#xff0c;我们总会遇到各种各样的技术问题&#xff0c;需要寻找合适的技术解决方案。而在互联网时代&#xff0c;我们可以快速通过搜索引擎获取丰富的技术资源和解决方案。然而&#xff0c;在不同的技术分享中&#xff0c;我们常常会遇到质量参差不齐的文…

eggjs

官网&#xff1a;快速入门 - Egg npm init egg --typesimple 在平时安装/下载依赖时候 控制栏出现如下报错时 npm ERR! code ENOLOCAL npm ERR! Could not install from "Files\nodejs\node_cache\_npx\13944" as it does not contain a package.json file. 解释:无…

【Linux 下】 信号量

文章目录 【Linux 下】 信号量信号量概念信号量操作初始化和销毁P&#xff08;&#xff09;操作V&#xff08;&#xff09;操作理解PV操作 基于信号量与环形队列实现的CS模型基于信号量和环形队列实现的生产者与消费者模型 【Linux 下】 信号量 信号量概念 信号量&#xff08;…

蓝莓投屏 - 超低延时投屏的投屏软件

蓝莓投屏是一个低延时投屏软件&#xff0c;支持安卓、iOS、Mac 设备与Windows系统的电脑之间互相投屏&#xff0c;包括手机/平板之间互投&#xff0c;手机投电脑&#xff0c;电脑投手机 等功能。 投屏画质达到4K高清&#xff0c;播放流畅无延迟。音视频同步&#xff0c;几乎没有…

无需OpenAI API Key,构建个人化知识库的终极指南

一、介绍 今天和大家一起学习下使用LangChain&#xff0b;LLM 来构建本地知识库。 我们先来了解几个名词。 二、什么是LLM&#xff1f; LLM指的是大语言模型&#xff08;Large Language Models&#xff09;&#xff0c;大语言模型&#xff08;LLM&#xff09;是指使用大量文…

Excel中正则表达式函数的使用

有这样一列 上海市闵行区七宝镇中春路7001号37栋 021-54881702 嘉定区黄渡镇金易路1号 021-69580001 如何将地址和电话分开 这两个分成2列&#xff08;地址和电话分开&#xff09; 第一列 第二列 上海市闵行区七宝镇中春路7001号37栋 021-54881702 嘉定区黄渡镇金易路1号 021-6…