UsernamePasswordAuthenticationFilter介绍

UsernamePasswordAuthenticationFilter是AbstractAuthenticationProcessingFilter针对使用用户名和密码进行身份验证而定制化的一个过滤器。其添加是在调用http.formLogin()时作用,默认的登录请求pattern为"/login",并且为POST请求。当我们登录的时候,也就是匹配到loginProcessingUrl,这个过滤器就会委托认证管理器authenticationManager来验证登录。

自定义UsernamePasswordAuthenticationFilter

这里我的需求是通过自定义UsernamePasswordAuthenticationFilter实现对前端传过来的密码进行RSA私钥解密,并且因为登录地址不是"/login",所以继承的是AbstractAuthenticationProcessingFilter,如果登录地址为默认,那么可直接继承UsernamePasswordAuthenticationFilter重写attemptAuthentication方法即可。

public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
private String privateKey = "xxxxxxxxxxxxxxxxxxx"; public MyUsernamePasswordAuthenticationFilter() {
super(new AntPathRequestMatcher("/oauth/token", "POST"));
} public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
try {
password = RSAUtil.decrypt(password, privateKey);
} catch (Exception e) {
e.printStackTrace();
} if (username == null) {
username = "";
} if (password == null) {
password = "";
} username = username.trim(); UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Allow subclasses to set the "details" property
setDetails(request, authRequest); return super.getAuthenticationManager().authenticate(authRequest);
} public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
} protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter).replaceAll(" ", "+");
} protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
} protected void setDetails(HttpServletRequest request,
UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
} public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
} public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
} public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
} public final String getUsernameParameter() {
return usernameParameter;
} public final String getPasswordParameter() {
return passwordParameter;
} }

把自定义 MyUsernamePasswordAuthenticationFilter 添加到 Filter Chain 过滤器链中

在 SpringSecurity 的配置类中使用 http.addFilterAt(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) 把自定义的过滤器放在UsernamePasswordAuthenticationFilter 的位置,并为其设置认证成功和失败的处理方法以及认证管理器AuthenticationManager

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired
private AuthenticationSuccessHandler appLoginInSuccessHandler; @Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and().httpBasic().and()
.cors().disable().headers().frameOptions().sameOrigin();// 解决iframe无法访问
http.addFilterAt(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
} @Bean
MyUsernamePasswordAuthenticationFilter myAuthenticationFilter() throws Exception {
MyUsernamePasswordAuthenticationFilter filter = new MyUsernamePasswordAuthenticationFilter();
filter.setAuthenticationManager(authenticationManagerBean());
filter.setAuthenticationSuccessHandler(appLoginInSuccessHandler);
filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSON.toJSONString(Respon.failed("登录失败!")));
}
});
return filter;
}
}

自定义UsernamePasswordAuthenticationFilter的运用

除了上面的例子,还常用于修改表单登录变为使用Json格式登录,登录验证码等等,需要注意的地方是UsernamePasswordAuthenticationFilter的默认登录地址为

SpringSecurity自定义UsernamePasswordAuthenticationFilter的更多相关文章

  1. SpringSecurity 自定义用户 角色 资源权限控制

    SpringSecurity 自定义用户 角色 资源权限控制 package com.joyen.learning.security; import java.sql.ResultSet; impor ...

  2. SpringSecurity 自定义表单登录

    SpringSecurity 自定义表单登录 本篇主要讲解 在SpringSecurity中 如何 自定义表单登录 , SpringSecurity默认提供了一个表单登录,但是实际项目里肯定无法使用的 ...

  3. Spring-Security 自定义Filter完成验证码校验

    Spring-Security的功能主要是由一堆Filter构成过滤器链来实现,每个Filter都会完成自己的一部分工作.我今天要做的是对UsernamePasswordAuthenticationF ...

  4. SpringSecurity自定义AuthenticationProvider和AuthenticationFilter

    AuthenticationProvider 默认实现:DaoAuthenticationProvider 授权方式提供者,判断授权有效性,用户有效性,在判断用户是否有效性,它依赖于UserDetai ...

  5. SpringSecurity自定义过滤器

    applicationContext-security.xml: <beans:beans xmlns="http://www.springframework.org/schema/s ...

  6. SpringSecurity自定义登陆页面和跳转页面

    如果我们不用form-login说明登陆界面,springsecurity框架将自动为我们生成登陆界面 现在我们不想用自动生成的登陆界面了,而想使用自定义的漂亮的登陆界面 则需要使用<secur ...

  7. springSecurity自定义认证配置

    上一篇讲了springSecurity的简单入门的小demo,认证用户是在xml中写死的.今天来说一下自定义认证,读取数据库来实现认证.当然,也是非常简单的,因为仅仅是读取数据库,权限是写死的,因为相 ...

  8. SpringSecurity自定义注解和处理器

    登录功能 添加一个配置类 @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Reso ...

  9. Spring-Security自定义登录页&inMemoryAuthentication验证

    Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架.框架下内容比较多,可以做到按照角色权限对请求路径进行限制.今天主要验证自定义登录页,在内存用户存储中进行请求 ...

随机推荐

  1. node一键发布,并运行

    作为一个前端开发人员如果你只会写一些业务代码,从程序员的角度来考虑已经可以了.但是从架构的角度来考虑那远远不够: 在此记录下成长中的经历: 想要达成的目的:运行一个脚本实现代码的打包,上传至服务器并部 ...

  2. 你真的了JMeter解聚合报告么?

    1.背景 大家在使用JMeter进行性能测试时,聚合报告(Aggregate Report)可以说是必用的监听器,但是你真的了解聚合报告么? 2.目的 本次笔者跟大家聊聊聚合报告(Aggregate ...

  3. AutoResetEvent控制线程用法

    本文主要来自一道面试题,由于之前对AutoResetEvent的用户很模糊(即使已经使用过了).面试题题目很简洁:两个线程交替打印0~100的奇偶数.你可以先动手试试,我主要是尝试在一个方法里面完成这 ...

  4. 【Spring Boot】利用 Spring Boot Admin 进行项目监控管理

    利用 Spring Boot Admin 进行项目监控管理 一.Spring Boot Admin 是什么 Spring Boot Admin (SBA) 是一个社区开源项目,用于管理和监视 Spri ...

  5. Gradle 是什么

    写在前面的话,最近在系统的学习Gradle,本来想写一篇关于 Gradle 的介绍. 但在官网发现了这篇关于 Gradle 的介绍,已经介绍的很好了,我就很直接翻译过来了. 原文地址 https:// ...

  6. Python学习 之 计算机基础

    第一章 计算机基础 1.1 硬件 计算机基本的硬件由:CPU / 内存 / 主板 / 硬盘 / 网卡 / 显卡 等组成,只有硬件但硬件之间无法进行交流和通信 1.2 操作系统 操作系统用于协同或控制硬 ...

  7. Django之ORM-model模型关系

    模型类关系 1)一对多关系例:图书类-英雄类 models.ForeignKey() 定义在多的类中. 2)多对多关系例:新闻类-新闻类型类 体育新闻 国际新闻models.ManyToManyFie ...

  8. Python面试总结篇

    Python Coding Interview Questions and Answers 面试题一:逻辑运算赋值 v1 = 1 or 9 v2 = 0 or 9 # print(v1, v2)会输出 ...

  9. slice splice(数组) 和 slice substr substring split (字符串)的区别

    array.slice(start,end)slice()如果不传入参数二,那么将从参数一的索引位置开始截取,一直到数组尾如果两个参数中的任何一个是负数,array.length会和它们相加 stri ...

  10. HBase的安装和使用

    文章作者:foochane  原文链接:https://foochane.cn/article/2019062801.html 1 Hbase基本介绍 Hbase是一个分布式数据库,可以提供数据的实时 ...