Springboot 整合 spring security,简单实现认证和授权

news2025/1/6 19:46:04

一.简介

Spring Security 是 Spring 家族中的一个安全管理框架。

一般来说,常见的安全管理技术栈的组合是这样的:

  1. SSM + Shiro
  2. Spring Boot/Spring Cloud + Spring Security

对于一个权限管理框架而言,无论是 Shiro 还是 Spring Security,最核心的功能,无非就是两方面:

  1. 认证
  2. 授权

认证就是我们常说的登录,授权就是权限鉴别,看看请求是否具备相应的权限。

虽然就是一个简简单单的登录,可是也能玩出很多花样来。

Spring Security 支持多种不同的认证方式,这些认证方式有的是 Spring Security 自己提供的认证功能,有的是第三方标准组织制订的,主要有如下一些:

一些比较常见的认证方式

  1. HTTP BASIC authentication headers:基于IETF RFC 标准。
  2. HTTP Digest authentication headers:基于IETF RFC 标准。
  3. HTTP X.509 client certificate exchange:基于IETF RFC 标准。
  4. LDAP:跨平台身份验证。
  5. Form-based authentication:基于表单的身份验证。
  6. Run-as authentication:用户用户临时以某一个身份登录。
  7. OpenID authentication:去中心化认证。

除了这些常见的认证方式之外,一些比较冷门的认证方式,Spring Security 也提供了支持,比如:

  1. Jasig Central Authentication Service:单点登录。
  2. Automatic “remember-me” authentication:记住我登录(允许一些非敏感操作)。
  3. Anonymous authentication:匿名登录。

作为一个开放的平台,Spring Security 提供的认证机制不仅仅是上面这些。如果上面这些认证机制依然无法满足你的需求,我们也可以自己定制认证逻辑。当我们需要和一些“老破旧”的系统进行集成时,自定义认证逻辑就显得非常重要了。

除了认证,剩下的就是授权了。

Spring Security 支持基于 URL 的请求授权(例如微人事)、支持方法访问授权以及对象访问授权。

这批文章,学习使用springboot框架集成spring security,实现一个简单的demo例子。

二.项目创建

使用idea创建springboot项目,这个自行百度怎么用idea创建springboot项目。

在 Spring Boot 中使用 Spring Security 非常容易,引入依赖即可,截图如下:
在这里插入图片描述

pom.xml 中的 Spring Security 依赖,代码如下:

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

只要加入依赖,项目的所有接口都会被自动保护起来。

三.初次体验

创建一个 HelloController类,代码如下:

@RestController
public class HelloController {
  @GetMapping("/hello")
   public String hello() {
        return "hello";
    }
}

访问 /hello ,需要登录之后才能访问,截图如下:
在这里插入图片描述
当用户从浏览器发送请求访问 /hello 接口时,服务端会返回 302 响应码,让客户端重定向到 /login 页面,用户在 /login 页面登录,登陆成功之后,就会自动跳转到 /hello 接口。

另外,也可以使用 POSTMAN 来发送请求,使用 POSTMAN 发送请求时,可以将用户信息放在请求头中(这样可以避免重定向到登录页面),截图如下:

在这里插入图片描述
通过以上两种不同的登录方式,可以看出,Spring Security 支持两种不同的认证方式:

  1. 通过 form 表单来认证
  2. 通过 HttpBasic 来认证

三.用户名配置

默认情况下,登录的用户名是 user ,密码则是项目启动时随机生成的字符串,可以从启动的控制台日志中看到默认密码,截图如下:
在这里插入图片描述

这个随机生成的密码,每次启动时都会变。对登录的用户名/密码进行配置,有三种不同的方式:

  1. 在 application.properties 中进行配置
  2. 通过 Java 代码配置在内存中
  3. 通过 Java 从数据库中加载

前两种比较简单,第三种代码量略大,本文就先来看看前两种,第三种后面再单独写文章介绍

3.1配置文件配置用户名/密码

可以直接在 application.properties 文件中配置用户的基本信息,代码如下:

spring.security.user.name=javaboy
spring.security.user.password=123

配置完成后,重启项目,就可以使用这里配置的用户名/密码登录了。

3.2Java 配置用户名/密码

也可以在 Java 代码中配置用户名密码,首先需要创建一个 Spring Security 的配置类,集成自 WebSecurityConfigurerAdapter 类,代码如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//下面这两行配置表示在内存中配置了两个用户
auth.inMemoryAuthentication()
.withUser("javaboy").roles("admin").password("$2a$10$OR3VSksVAmCzc.7WeaRPR.t0wyCsIj24k0Bne8iKWV1o.V9wsP8Xe")
.and()
.withUser("lisi").roles("user").password("$2a$10$p1H8iWa8I4.CA.7Z8bwLjes91ZpY.rYREGHQEInNtAp4NzL6PLKxi");
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

这里我们在 configure 方法中配置了两个用户,用户的密码都是加密之后的字符串(明文是 123),从 Spring5 开始,强制要求密码要加密,如果非不想加密,可以使用一个过期的 PasswordEncoder 的实例 NoOpPasswordEncoder,但是不建议这么做,毕竟不安全。

Spring Security 中提供了 BCryptPasswordEncoder 密码编码工具,可以非常方便的实现密码的加密加盐,相同明文加密出来的结果总是不同,这样就不需要用户去额外保存 盐的字段了,这一点比 Shiro 要方便很多。

四.用户名配置

对于登录接口,登录成功后的响应,登录失败后的响应,我们都可以在 WebSecurityConfigurerAdapter 的实现类中进行配置。代码如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
VerifyCodeFilter verifyCodeFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()//开启登录配置
.antMatchers("/hello").hasRole("admin")//表示访问 /hello 这个接口,需要具备 admin 这个角色
.anyRequest().authenticated()//表示剩余的其他接口,登录之后就能访问
.and()
.formLogin()
//定义登录页面,未登录时,访问一个需要登录之后才能访问的接口,会自动跳转到该页面
.loginPage("/login_p")
//登录处理接口
.loginProcessingUrl("/doLogin")
//定义登录时,用户名的 key,默认为 username
.usernameParameter("uname")
//定义登录时,用户密码的 key,默认为 password
.passwordParameter("passwd")
//登录成功的处理器
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("success");
out.flush();
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("fail");
out.flush();
}
})
.permitAll()//和表单登录相关的接口统统都直接通过
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("logout success");
out.flush();
}
})
.permitAll()
.and()
.httpBasic()
.and()
.csrf().disable();
}
}

我们可以在 successHandler 方法中,配置登录成功的回调,如果是前后端分离开发的话,登录成功后返回 JSON 即可,同理,failureHandler 方法中配置登录失败的回调,logoutSuccessHandler 中则配置注销成功的回调。

五.忽略拦截

如果某一个请求地址不需要拦截的话,有两种方式实现:

  1. 设置该地址匿名访问
  2. 直接过滤掉该地址,即该地址不走 Spring Security 过滤器链

推荐使用第二种方案,代码如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/vercode");
}
}

Spring Security 另外一个强大之处就是它可以结合 OAuth2

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

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

相关文章

tf.image.decode_jpeg(别名tf.io.decode_jpeg)函数工作原理分析

1 问题提出 最近在阅读某个论文的源代码时&#xff0c; 发现作者在读取图像数据时没有使用PIL.Image或opencv库&#xff0c;而是使用了tf.image.decode_jpeg&#xff0c;代码节选如下&#xff1a; # tf1中的函数, 用于读取文件 # tf2中该函数更改为了tf.io.read_file image_c…

【Linux权限的概念及理解】

目录 一、认识linux下的用户分类二、什么叫权限三、没有权限会怎么样&#xff08;见一见&#xff09;四、权限的修改问题4.1chmod指令4.2chown指令4.3chgrp指令 五、两个问题粘滞位5.1Question15.2Question25.3粘滞位 一、认识linux下的用户分类 Linux下有两种用户&#xff1a…

mysql中的Redo log

目录标题 前言redolog保证持久性redolog工作过程 redo log中的WAL&#xff08;先写日志&#xff0c;再写磁盘【写入redo log file】&#xff09;刷盘策略 重要参数innodb_flush_log_at_trx_commit如何选择 Redo log file日志文件日志文件组redo log刷盘与数据页刷盘redo log何时…

Vue CLI Todo-List案例

3.7. Todo-List 案例 组件化编码流程 拆分静态组件&#xff1a;组件要按照功能点拆分&#xff0c;命名不要与html元素冲突实现动态组件&#xff1a;考虑好数据的存放位置&#xff0c;数据是一个组件在用&#xff0c;还是一些组件在用 一个组件在用&#xff1a;放在组件自身即…

Cesium入门之八:Cesium加载矢量数据

目录 一、什么是矢量数据二、Cesium支持的矢量数据格式KML格式KmlDataSource CZML格式CzmlDataSource GeoJSON格式GeoJsonDataSource 三、Cesium加载GeoJSON数据格式的中国地图示例 一、什么是矢量数据 矢量数据是用于描述地理空间几何特征的一类基于向量的地理信息数据&#…

RabbitMQ的几种通讯方式及其代码示例

文章目录 一、引言二、RabbitMQ介绍三、RabbitMQ安装四、RabbitMQ架构4.1 官方的简单架构图4.2 RabbitMQ的完整架构图4.3 RabbitMQ 通讯方式4.4 Hello-World案例演示4.5 基本原理 五、SpringBoot整合RabbitMQ的使用5.1 导入依赖5.2 在application.properties中增加配置5.3 Hell…

前端学习--Vue(2)

一、Vue简介 1.1 概念 Vue是一套用于构建用户界面的前端框架 框架&#xff1a;现成解决方案&#xff0c;遵守规范去编写业务功能 指令、组件、路由、Vuex、vue组件库 1.2 特性 数据驱动视图 vue连接页面结构和数据&#xff0c;监听数据变化&#xff0c;自动渲染页面结构…

Vue--》Vue 3 路由进阶——从基础到高级的完整指南

目录 Vue3中路由讲解与使用 路由的安装与使用 路由模式的使用 编程式路由导航 路由传参 嵌套路由 命名视图 重定向与别名 Vue3中路由讲解与使用 Vue 路由是 Vue.js 框架提供的一种机制&#xff0c;它用于管理网页上内容的导航。Vue 路由可以让我们在不刷新页面的情况下…

【ChatGPT】通过 ChatGPT 用文字描述来绘制插画

点击上方“独立开发者杂谈” 喜欢本文&#xff0c;请置顶或星标 使用文字描述绘制插画具有以下好处 无需绘画技巧&#xff0c;体验与AI结合&#xff0c;创意灵活性&#xff0c;节省时间。 使用 Figma 工具 Figma &#xff08;https://www.figma.com&#xff09;是一款流行的设计…

Linux:iptables防火墙

Linux&#xff1a;iptables防火墙 一、iptables防火墙概述1.1 iptables防火墙1.2 netfilter/iptables 关系 二、Linux防火墙基础2.1 iptables的表、链结构2.2 数据包控制的匹配流程 三、编写防火墙规则3.1 基本语法、控制类型3.2 添加、查看、删除规则等3.3 规则的匹配条件3.3.…

黑马Redis原理篇

黑马Redis原理篇 1、数据结构1.1、动态字符串SDS1.2、IntSet1.3、Dict1.4、ZipList1.5、QuickList1.6、SkipList1.7、RedisObject1.8、五种数据结构1. String&#xff08;小EMBSTR,大RAW (SDS),少量整数INT&#xff09;2. List&#xff08;Redis3.2之后使用QuickList实现&#…

CSDN周赛52期及53期浅析

好久没写题解了&#xff0c;没办法&#xff0c;C站的题目更新的速度太慢了&#xff0c;重复考过去的老题已经不能再进步了。52期还混了个名次&#xff0c;总要写篇文章完成一下任务。而53期就惨了去了&#xff0c;三道选择题全蒙错了。 反正我个人觉得在现在C站的OJ环境里考选…

手撸鉴权系统——SpringBoot2+Vue2(一定惊喜满满,万字长文)

初衷&#xff1a; 一直不太理解整个前后端的鉴权&#xff0c;跨域等问题&#xff0c;抽空两个晚上整理出万字文章&#xff0c;也是对于自己的一个交代&#xff0c;现在共享出来&#xff0c;希望大家也能受益&#xff0c;将使用过程在这里一一详述&#xff0c;还是多说一句&…

【图论(1)】图的存储、遍历与拓扑排序

5月16-5月18日学习内容 文章目录 一、图是什么二、图的存储1、直接存边法2、邻接矩阵法3、邻接表法4、链式前向星时间复杂度分析 三、图的遍历DFSBFS 四、拓扑排序&#xff08;今天实在没时间写了&#xff0c;明天写&#xff09; 一、图是什么 这是oi.wiki给的定义 简而言之…

ENVI制图——土地利用专题图

ENVI制图 0 前言1 数据准备2 数据预处理2.1 先在arcmap中把数据导出为tif格式&#xff0c;然后加入envi&#xff08;别问我为什么要先用arcmap处理&#xff0c;因为这是envi制图教程 :( &#xff09;2.2 直接把tif格式的数据拖进envi&#xff0c;此时看不到数据类别&#xff0c…

低代码+AI:助力企业数字化转型,揭示未来发展趋势

问个问题&#xff1a;你有没有亲自去了解、使用近期爆火的生成式人工智能——ChatGPT&#xff1f; 如果答案是否定的&#xff0c;作为企业数字化转型的前沿先锋小Z&#xff0c;建议你一定要去亲自尝试它。虽然人工智能技术已经发展多年&#xff0c;但OpenAI所发布的ChatGPT&…

瑞吉外卖 - 新增菜品功能(16)

某马瑞吉外卖单体架构项目完整开发文档&#xff0c;基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成&#xff0c;有需要的胖友记得一键三连&#xff0c;关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料&#xff1a;https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

(十)Spring源码阅读:finishBeanFactoryInitialization方法

一、概述 该方法是实例化bean的主要方法&#xff0c;它实现的主要流程如下图所示。 这是方法执行的主要流程图。 具体执行流程如下图&#xff0c;我们将按照具体执行流程一个个介绍具体的方法。 二、主要方法 finishBeanFactoryInitialization内部调用了getBean方法。 getBea…

AIGC+机器人=具身智能?硅谷最酷的两个男人不谋而合预演“下个浪潮”

收集整理|小鱼新的AI题材层出不穷&#xff0c;这次轮到“机器人AI"融合而成的具身智能概念。 “硅谷钢铁侠"马斯克和热爱黑色皮衣的"显卡教父”黄仁勋均作出积极表态&#xff0c;可谓不谋而合。 当地时间5月16日&#xff0c;特斯拉2023年年度股东大会召开&…

unity DoTween动画插件的使用(最全)

DOTween是最常用的动画插件之一,比使用Unity自带脚本写动画,方便很多。 插件获取 untiy商店插件地址 https://assetstore.unity.com/packages/tools/animation/dotween-hotween-v2-27676 DOTween商城地址,开发文档 http://dotween.demigiant.com 导入和设置 DOTween首次使…