一文彻底搞定Spring Security 认证,实现登陆登出功能
Spring Security 是一个强大且灵活的安全框架,提供了身份验证(认证)和授权(授权)功能。下面我们将详细介绍 Spring Security 的认证功能流程,并提供自定义实现登录接口的示例,包括自定义认证过滤器和登出功能。
一、Spring Security 认证流程的深入分析
Spring Security 的认证流程是多层次的,涉及多个组件的协作。以下是每个步骤的深入分析:
请求拦截
当用户请求一个受保护的资源时,Spring Security 会使用过滤器链来处理请求。
FilterChainProxy是 Spring Security 的核心过滤器,它将请求传递给注册的过滤器链。认证过滤器
默认情况下,
UsernamePasswordAuthenticationFilter会被用作处理用户名和密码的认证。它从请求中提取认证信息,通常是通过 POST 请求的表单数据传递。关键方法
attemptAuthentication中,使用AuthenticationManager来处理认证请求。AuthenticationManager负责委托认证给具体的认证提供者。用户详情服务(UserDetailsService)
认证过程中的一个重要步骤是从数据源中加载用户信息。
UserDetailsService接口提供了一个loadUserByUsername方法,负责根据用户名加载用户详情。通常,用户信息存储在数据库中,
UserDetails对象将包含用户名、密码和权限信息。Spring Security 提供了多种UserDetailsService的实现,开发者也可以自定义实现。密码验证
一旦获取到用户详情,接下来的步骤是验证密码。使用
PasswordEncoder对用户输入的密码与存储在数据库中的密码进行比对。Spring Security 支持多种加密算法(如 BCrypt、PBKDF2、SCrypt),并允许开发者自定义密码编码器。
成功和失败处理
认证成功后,
successfulAuthentication方法被调用。在此方法中,开发者可以实现自定义的成功逻辑,例如返回 JWT 令牌、设置用户会话等。如果认证失败,
unsuccessfulAuthentication方法会被调用,可以根据需要返回错误消息或重定向到登录页面。
二、自定义登录接口的实现
1. 自定义认证过滤器的设计
创建自定义认证过滤器时,需要继承 UsernamePasswordAuthenticationFilter 并重写相应的方法。以下是详细实现:
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
public CustomAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String username = request.getParameter("username");
String password = request.getParameter("password");
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
return authenticationManager.authenticate(authenticationToken);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
// 可以返回用户信息或 JWT 令牌
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
ObjectMapper objectMapper = new ObjectMapper();
String token = "some_generated_jwt"; // 实际上要生成 JWT
response.getWriter().write(objectMapper.writeValueAsString("token: " + token));
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"error\": \"" + failed.getMessage() + "\"}");
}
}
2. 配置 Spring Security 的详细步骤
在配置类中,我们将添加自定义过滤器并设置用户存储方式。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 配置用户存储方式
auth.inMemoryAuthentication()
.withUser("user").password("{noop}password").roles("USER")
.and()
.withUser("admin").password("{noop}admin").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
CustomAuthenticationFilter customFilter = new CustomAuthenticationFilter(authenticationManagerBean());
customFilter.setFilterProcessesUrl("/login"); // 自定义登录路径
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll() // 允许访问登录接口
.anyRequest().authenticated() // 其他请求需要认证
.and()
.addFilter(customFilter) // 添加自定义认证过滤器
.logout()
.logoutUrl("/logout") // 自定义登出路径
.logoutSuccessUrl("/login?logout") // 登出成功后的重定向地址
.invalidateHttpSession(true) // 登出时使 HTTP 会话失效
.deleteCookies("JSESSIONID"); // 删除指定的 Cookie
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
三、登出功能的实现
在 Spring Security 中,登出功能非常简单。配置登出路径和成功重定向即可。在上述配置中,我们已经为登出功能添加了以下配置:
logoutUrl("/logout"):指定登出的 URL。logoutSuccessUrl("/login?logout"):登出成功后的重定向 URL。invalidateHttpSession(true):登出时使 HTTP 会话失效。deleteCookies("JSESSIONID"):在登出时删除指定的 Cookie。
四、设计考虑与常见问题
设计考虑
灵活性:自定义认证过滤器允许我们实现不同的认证逻辑,如 OAuth2、JWT 等,保持系统的灵活性。
安全性:在实现过程中,确保敏感信息(如密码)不被明文传输和存储,推荐使用 HTTPS 和合适的密码加密方式。
错误处理:对失败的认证提供明确的反馈,方便用户理解问题所在,提升用户体验。
常见问题
跨域问题:在前后端分离的应用中,登录接口可能会遇到跨域请求问题。可以通过设置 CORS 策略来解决。
状态管理:如果使用 JWT 进行认证,需注意如何管理状态和续期机制。
并发登录问题:需要考虑多个设备或浏览器同时登录的情况,可能需要实现会话管理。
一文彻底搞定Spring Security 认证,实现登陆登出功能的更多相关文章
- 【项目实践】一文带你搞定Spring Security + JWT
以项目驱动学习,以实践检验真知 前言 关于认证和授权,R之前已经写了两篇文章: [项目实践]在用安全框架前,我想先让你手撸一个登陆认证 [项目实践]一文带你搞定页面权限.按钮权限以及数据权限 在这两篇 ...
- spring security 认证源码跟踪
spring security 认证源码跟踪 在跟踪认证源码之前,我们先根据官网说明一下security的内部原理,主要是依据一系列的filter来实现,大家可以根据https://docs.sp ...
- Spring Security认证配置(三)
学习本章之前,可以先了解下上篇Spring Security认证配置(二) 本篇想要达到这样几个目的: 1.登录成功处理 2.登录失败处理 3.调用方自定义登录后处理类型 具体配置代码如下: spri ...
- 3步轻松搞定Spring Boot缓存
作者:谭朝红 前言 本次内容主要介绍基于Ehcache 3.0来快速实现Spring Boot应用程序的数据缓存功能.在Spring Boot应用程序中,我们可以通过Spring Caching来快速 ...
- 用Hopper搞定Mac迅雷的会员以及离线下载功能
转自 用Hopper搞定Mac迅雷的会员以及离线下载功能 先定位Mac迅雷的可执行文件 snakeninnys-iMac:~ snakeninny$ ls /Applications/Thunder. ...
- spring security+freemarker获取登陆用户的信息
spring security+freemarker获取登陆用户的信息 目标页面之间获取 ${Session.SPRING_SECURITY_CONTEXT.authentication.princi ...
- 一文搞定Spring Boot + Vue 项目在Linux Mysql环境的部署(强烈建议收藏)
本文介绍Spring Boot.Vue .Vue Element编写的项目,在Linux下的部署,系统采用Mysql数据库.按照本文进行项目部署,不迷路. 1. 前言 典型的软件开发,经过" ...
- Spring Security 入门(1-4-2)Spring Security - 认证过程之AuthenticationProvider的扩展补充说明
1.用户信息从数据库获取 通常我们的用户信息都不会向第一节示例中那样简单的写在配置文件中,而是从其它存储位置获取,比如数据库.根据之前的介绍我们知道用户信息是通过 UserDetailsService ...
- Spring Security 入门(1-4-1)Spring Security - 认证过程
理解时可结合一下这位老兄的文章:http://www.importnew.com/20612.html 1.Spring Security的认证过程 1.1.登录过程 - 如果用户直接访问登录页面 用 ...
- Authentication讲解(Spring security认证)
标准认证过程: 1.用户使用username和password登录 2.系统验证这个password对于该username是正确的 3.假设第二步验证成功,获取该用户的上下文信息(如他的角色列表) 4 ...
随机推荐
- [粉丝问答16]应届生被放鸽子,怒怼HR!找工作和找对象哪个更残酷?
很多应届生在求职过程中遇到过被放鸽子的情况,但是由于段位不高,资源不够,社会阅历尚浅,很多人都是忍气吐声,但是也不乏有些学生性格刚硬,怒怼的. 比如下面这位学生,竟然直接怼了HR. 0.应届硕士小伙怒 ...
- CF1234D
CF1234D 链接: https://codeforces.com/problemset/problem/1234/D 题目大意: 给你一个字符串s,你需要完成如下q次询问 把 s 的第 p 位改为 ...
- Minnaert
Minnaert 假设气泡关闭时发生周期性膨胀和收缩,周围水也跟着振动,就嗷地一声叫了出来!设有个半径为 \(r\) 的泡形成后开始简谐振动,半径有 \[r=r_0+a\sin\frac{2\pi t ...
- BST 二叉搜索树 BinarySearchTree C++实现(递归/非递归)
目录 二叉搜索树 基本概念 常用结论 用途 二叉搜索树的性能分析 二叉搜索树的操作 查找 插入 删除 代码实现 BSTree.hpp test.cc 二叉搜索树 基本概念 二叉搜索树(BST,Bina ...
- Vue 项目 毒鸡汤 壮士可要来一碗!
项目灵感来自"聆听远方"的毒鸡汤 非常简单 适合 Vue 新童鞋 按国际惯例 先上图 来不及解释了 快把代码复制走 poison-soup.html <!DOCTYPE ht ...
- 组合逻辑环(Combinational Logic Loop)
组合逻辑电路 组合逻辑电路是数字电子学中一类基本的电路类型,它由一系列逻辑门组成,用于实现特定的逻辑功能.与时序逻辑电路不同,组合逻辑电路的输出完全取决于当前的输入信号,而不受之前输入的影响.换句话说 ...
- Swahili-text:华中大推出非洲语言场景文本检测和识别数据集 | ICDAR 2024
论文提出了一个专门针对斯瓦希里语自然场景文本检测和识别的数据集,这在当前研究中是一个未充分开发的语言领域.数据集包括976张带标注的场景图像,可用于文本检测,以及8284张裁剪后的图像用于识别. 来源 ...
- cubeide汉化包地址
http://mirrors.ustc.edu.cn/eclipse/technology/babel/update-site 具体步骤看洋桃物联网入门30步的视频
- 扩展KMP (ex_KMP)
一些约定: 字符串下标从1开始 s[1,i]表示S的第一个到第i个字符组成的字符串 解决的题型: 给你两个字符串A,B(A.size()=n,B.size()=m),求p数组 p[i]表示最大的len ...
- 【YashanDB知识库】数据库审计shutdown immediate操作导致数据库异常退出
[问题分类]功能使用 [关键字]数据库审计,shutdown immediate [问题描述]审计shutdown immediate 操作,数据库作主从切换时会导致数据库异常退出. [问题原因分析] ...