/*
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.springframework.security.web.authentication; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert; /**
* Processes an authentication form submission. Called
* {@code AuthenticationProcessingFilter} prior to Spring Security 3.0.
* <p>
* Login forms must present two parameters to this filter: a username and password. The
* default parameter names to use are contained in the static fields
* {@link #SPRING_SECURITY_FORM_USERNAME_KEY} and
* {@link #SPRING_SECURITY_FORM_PASSWORD_KEY}. The parameter names can also be changed by
* setting the {@code usernameParameter} and {@code passwordParameter} properties.
* <p>
* This filter by default responds to the URL {@code /login}.
*
* @author Ben Alex
* @author Colin Sampaleanu
* @author Luke Taylor
* @since 3.0
*/ /**
* 当用户登录的时候 当前的过滤器会被调用
*/
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { //表单提交的 用户名
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username"; // 说明 如果用户想增强当前类的功能可以创建一个当前类的子类 在子类的构造方法中 修改SPRING_SECURITY_FORM_USERNAME_KEY和SPRING_SECURITY_FORM_PASSWORD_KEY
// 并且增加到过滤器链中 使用 addfilterAt(new 子类, 当前类.class)
//表单提交的 密码 必须以SPRING_SECURITY_FORM_PASSWORD_KEY 为主
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password"; // 规定请求路径 以及请求方式
private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/login",
"POST"); // 用户名 传递参数解析的Key
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
// 密码 传递参数解析的Key
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY; // 哪一种方式的登录请求 - 仅限于POST
private boolean postOnly = true; // 初始化
public UsernamePasswordAuthenticationFilter() {
super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
} /**
* 初始化
* @param authenticationManager 认证管理器
*/
public UsernamePasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);
} /*
当用户调用 /login 时会被调用
此方法为重新父类方法。 用户可以继承父类实现自定义的表单登录方法
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
// 如果不是POST调用的话那么抛出 授权服务 异常
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
// 解析获取username
String username = obtainUsername(request);
// 如果user 不为空的话 放入内存并且返回
// 下次在其他用户调用的时候 直接返回而不是重新生成。 这里可能是考虑的用户ID可能会出现多次调用的时候对内存的优化
username = (username != null) ? username.trim() : "";
// 与上述但是直接返回
String password = obtainPassword(request);
password = (password != null) ? password : "";
/**
* UsernamePasswordAuthenticationToken 是在用户登录时 loadUserByUsername 返回的对象一致。用户可以在当前
* 处理自己的登录逻辑
* 由于此处我这里是 使用的oauth 所以在默认的登录中是未授权的 用户
* 至于为什么这里写的这么详细呢 ? 是因为有些课程中老师的习惯是重写这个接口实现用户的登录
* 有的老师是重写的loadUserByUsername 两者皆可 避免混淆
*/
UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
password); // Allow subclasses to set the "details" property
setDetails(request, authRequest);
//返回
return this.getAuthenticationManager().authenticate(authRequest);
} /**
* Enables subclasses to override the composition of the password, such as by
* including additional values and a separator.
* <p>
* This might be used for example if a postcode/zipcode was required in addition to
* the password. A delimiter such as a pipe (|) should be used to separate the
* password and extended value(s). The <code>AuthenticationDao</code> will need to
* generate the expected password in a corresponding manner.
* </p>
* @param request so that request attributes can be retrieved
* @return the password that will be presented in the <code>Authentication</code>
* request token to the <code>AuthenticationManager</code>
*/ // 从http请求获取password
@Nullable
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(this.passwordParameter);
} /**
* Enables subclasses to override the composition of the username, such as by
* including additional values and a separator.
* @param request so that request attributes can be retrieved
* @return the username that will be presented in the <code>Authentication</code>
* request token to the <code>AuthenticationManager</code>
*/
// 从http请求获取username
@Nullable
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(this.usernameParameter);
} /**
* Provided so that subclasses may configure what is put into the authentication
* request's details property.
* @param request that an authentication request is being created for
* @param authRequest the authentication request object that should have its details
* set
*/
//设置信息 子类可访问
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
} /**
* Sets the parameter name which will be used to obtain the username from the login
* request.
* @param usernameParameter the parameter name. Defaults to "username".
*/ // 自定义登录的解析参数
public void setUsernameParameter(String usernameParameter) {
Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
this.usernameParameter = usernameParameter;
} /**
* Sets the parameter name which will be used to obtain the password from the login
* request..
* @param passwordParameter the parameter name. Defaults to "password".
*/
//设置密码的解析Parame 表单的name属性
public void setPasswordParameter(String passwordParameter) {
Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
this.passwordParameter = passwordParameter;
} /**
* Defines whether only HTTP POST requests will be allowed by this filter. If set to
* true, and an authentication request is received which is not a POST request, an
* exception will be raised immediately and authentication will not be attempted. The
* <tt>unsuccessfulAuthentication()</tt> method will be called as if handling a failed
* authentication.
* <p>
* Defaults to <tt>true</tt> but may be overridden by subclasses.
*/ public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
} public final String getUsernameParameter() {
return this.usernameParameter;
} public final String getPasswordParameter() {
return this.passwordParameter;
} }

最新文章

  1. java:集合的自定义多重排序
  2. ASP.NET MVCでResponse Headerのサーバーバージョンをどうやって隠しますか?
  3. afasf
  4. cocos引擎v2.1版本android 编译问题解决办法 (cocos2d-x-3.4rc1)
  5. node中的模块
  6. app进入后台申请10分钟活跃时间-b
  7. 分享10个Js的小型库,效果真的很棒
  8. [walkthrough] 在Asp.net MVC6 RC里使用NLog,并且把配置集成到config.json
  9. swift 协议传值的实现
  10. JS添加类似C# string.Format方法
  11. 0_Simple__simpleAssert + 0_Simple__simpleAssert_nvrtc
  12. 浅谈ES6
  13. BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]
  14. 随机ID添加
  15. [转]C# 之DLL调用(托管与非托管)
  16. 免费了 -- EXCEL插件 智表ZCELL 普及版V1.0 发布了!!!
  17. css第二天
  18. Java之Date Time API (Java 8 新特性)
  19. yum 命令下载安装Openjdk
  20. 在 ServiceModel 客户端配置部分中,找不到引用协定“IpsBarcode.ScanService”的默认终结点元素。这可能是因为未找到应用程序的配置文件,或者是因为客户端元素中找不到与此协定匹配的终结点元素。

热门文章

  1. TCP通信的客户端代码实现-TCP通信的服务器端代码实现
  2. Node.js学习笔记----day02
  3. Matlab导入多个.mat文件进行画图
  4. 力扣---167. 两数之和 II - 输入有序数组
  5. mysql16 sql优化-order by-GROUP BY
  6. python判断密码连续,重复,大小写、数字、符号混合密码复杂度要求
  7. 郁金香 对MFC 编辑框的查看 与更改
  8. LG P3809 【模板】后缀排序
  9. mongodump导出mongodb中的数据
  10. unity puerTS热更