Spring Security在登录验证中增加额外数据(如验证码)
在使用Spring Security框架过程中,经常会有这样的需求,即在登录验证时,附带增加额外的数据,如验证码、用户类型等。下面将介绍如何实现。
注:我的工程是在Spring Boot框架基础上的,使用xml方式配置的话请读者自行研究吧。
- 实现自定义的WebAuthenticationDetails
该类提供了获取用户登录时携带的额外信息的功能,默认实现WebAuthenticationDetails提供了remoteAddress与sessionId信息。开发者可以通过Authentication的getDetails()获取WebAuthenticationDetails。我们编写自定义类CustomWebAuthenticationDetails继承自WebAuthenticationDetails,添加我们关心的数据(以下是一个token字段)。
package com.cgs.courses.service;
import javax.servlet.http.HttpServletRequest;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {
/**
*
*/
private static final long serialVersionUID = 6975601077710753878L;
private final String token;
public CustomWebAuthenticationDetails(HttpServletRequest request) {
super(request);
token = request.getParameter("token");
}
public String getToken() {
return token;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append("; Token: ").append(this.getToken());
return sb.toString();
}
}
注:在登录页面,可将token字段放在form表单中,也可以直接加在url的参数中,进而把额外数据发送给后台。
- 实现自定义的AuthenticationDetailsSource
该接口用于在Spring Security登录过程中对用户的登录信息的详细信息进行填充,默认实现是WebAuthenticationDetailsSource,生成上面的默认实现WebAuthenticationDetails。我们编写类实现AuthenticationDetailsSource,用于生成上面自定义的CustomWebAuthenticationDetails。
package com.cgs.courses.service; import javax.servlet.http.HttpServletRequest; import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component; @Component
public class CustomAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> { @Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
return new CustomWebAuthenticationDetails(context);
}
}
- 配置使用自定义的AuthenticationDetailsSource
只要看这一句.formLogin().authenticationDetailsSource(authenticationDetailsSource)
@Autowired
private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource; protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.cacheControl()
.contentTypeOptions()
.httpStrictTransportSecurity()
.xssProtection()
.and()
.authorizeRequests()
.antMatchers(
"/css/**",
"/js/**")
.permitAll()
.antMatchers("/**")
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.defaultSuccessUrl("/todo.html", true)
.authenticationDetailsSource(authenticationDetailsSource)
.and()
.logout()
.logoutUrl("/logout")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login")
.and()
.csrf().disable();
}
- 实现自定义的AuthenticationProvider
AuthenticationProvider提供登录验证处理逻辑,我们实现该接口编写自己的验证逻辑。
package com.cgs.courses.service; import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component; @Component
public class CustomAuthenticationProvider implements AuthenticationProvider { @Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
CustomWebAuthenticationDetails details = (CustomWebAuthenticationDetails) authentication.getDetails(); // 如上面的介绍,这里通过authentication.getDetails()获取详细信息
// System.out.println(details); details.getRemoteAddress(); details.getSessionId(); details.getToken();
// 下面是验证逻辑,验证通过则返回UsernamePasswordAuthenticationToken,
// 否则,可直接抛出错误(AuthenticationException的子类,在登录验证不通过重定向至登录页时可通过session.SPRING_SECURITY_LAST_EXCEPTION.message获取具体错误提示信息)
if (验证通过) {
return UsernamePasswordAuthenticationToken(省略参数);
} else {
throw new AuthenticationException的子类("你要显示的错误信息")
}
} @Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
} }
- 配置使用自定义的AuthenticationProvider
@Autowired
private AuthenticationProvider authenticationProvider; @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
Spring Security在登录验证中增加额外数据(如验证码)的更多相关文章
- Spring Boot整合Spring Security自定义登录实战
本文主要介绍在Spring Boot中整合Spring Security,对于Spring Boot配置及使用不做过多介绍,还不了解的同学可以先学习下Spring Boot. 本demo所用Sprin ...
- 自定义Spring Security的身份验证失败处理
1.概述 在本快速教程中,我们将演示如何在Spring Boot应用程序中自定义Spring Security的身份验证失败处理.目标是使用表单登录方法对用户进行身份验证. 2.认证和授权(Authe ...
- Spring Security 自定义登录认证(二)
一.前言 本篇文章将讲述Spring Security自定义登录认证校验用户名.密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Se ...
- spring security关闭http验证 和 springboot 使用h2数据库
spring security关闭http验证 最近在跑demo的过程中,访问swagger页面的时候需要验证登录,记得在之前写的代码中是关闭了security验证,无需登录成功访问,直接在appli ...
- Spring Security 概念基础 验证流程
Spring Security 概念基础 验证流程 认证&授权 认证:确定是否为合法用户 授权:分配角色权限(分配角色,分配资源) 认证管理器(Authentication Manager) ...
- springboot中使用spring security,登录url就出现403错误
参考链接:https://segmentfault.com/q/1010000012743613 有两个controller,一个是所有用户可以访问的@RequestMapping("use ...
- Spring Security 基础登录实例
1 新建Java Web项目 导入Jar: 2 修改web.xml <?xml version="1.0" encoding="UTF-8"?> & ...
- SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能
在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的方式,Spring Security 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...
- spring security结合数据库验证用户-XML配置方式
之前的用户信息我们都是使用的内存用户,测试例子可以,实际中使用肯定不行,需要结合数据库进行验证用户.这就是本节的重点: 项目目录如下: 在之前的项目中的依赖中添加两个依赖: <dependen ...
随机推荐
- 一篇关于ajax跨域问题的解决方案
这几天没事,我有一个好友,让我帮他做一个机器人对话demo, 我说 看看有没有时间(其实自己一脸懵逼) 然后百度了一下,发现了一个机器人 -(连接就不弄出来了,可以私底下交流) ,,我是用这个的 好 ...
- PAT Basic 1062 最简分数 (20 分)
一个分数一般写成两个整数相除的形式:/,其中 M 不为0.最简分数是指分子和分母没有公约数的分数表示形式. 现给定两个不相等的正分数 / 和 /,要求你按从小到大的顺序列出它们之间分母为 K 的最简分 ...
- mysql存储json
1. json_merge 合并Json并返回 update `user` set inviteeMap = json_merge(inviteeMap, '{"xx1":100} ...
- async 与 await
async 关键字 1.含义:表示函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 2.定义与调用 async function hello (flag) { if (flag) { re ...
- 技术学到多厉害,才能顺利进入BAT?
简介 本科的时候对 Linux 特别感兴趣,心中向往成为一名运维工程师,就开始没日没夜的看相关的书籍,到了大约2013年前后的时候发现 DevOps 开始流行起来了,就开始学习 Python 希望成为 ...
- metal2 里 programmable blending 和image block的区别 语法以及persistent thread group的语法
programmable blending 刚接触这个概念的时候 挺激动的 因为能解决很多管线里面的问题 比如 切一次rt再切回来 为了做read write same rt 有了这个 就不用切啦 可 ...
- For 循环的嵌套与九九乘法表
㈠通过程序,在页面中输入如下图形 * * * * * * * * * * * * * * * * * * * * * * * * * 代码如下: //向body中输入一个内容 //document. ...
- removeClass([class|fn])
removeClass([class|fn]) 概述 从所有匹配的元素中删除全部或者指定的类.直线电机生产厂家 参数 classStringV1.0 一个或多个要删除的CSS类名,请用空格分开 f ...
- HDU 5527 Too Rich ( 15长春区域赛 A 、可贪心的凑硬币问题 )
题目链接 题意 : 给出一些固定面值的硬币的数量.再给你一个总金额.问你最多能用多少硬币来刚好凑够这个金额.硬币数量和总金额都很大 分析 : 长春赛区的金牌题目 一开始认为除了做类似背包DP那样子 ...
- DP(第一版)
序 任何一种具有递推或者递归形式的计算过程,都叫做动态规划 如果你一开始学的时候就不会DP,那么你在考试的时候就一定不会想到用动态规划! 需要进行掌握的内容 1)DP中的基本概念 2)状态 3)转移方 ...