|

1.创建MobileAuthenticationFilter , 模仿 UsernamePasswordAuthenticationFilter 代码进行改造
2.按ctrl+n,搜索UsernamePasswordAuthenticationFilter
UsernamePasswordAuthenticationFilter是校验用户名密码的,
我们只要模仿它写一个校验手机号的就行了

3. 全部复制UsernamePasswordAuthenticationFilter的代码到MobileAuthenticationFilter

修改前源码
package com.cis.security.authentication.mobile;
import org.springframework.lang.Nullable;
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.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 用于校验用户手机号是否允许通过认证
*/
public class MobileAuthenticationFilter 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 = "username";
private String passwordParameter = "password";
private boolean postOnly = true;
public UsernamePasswordAuthenticationFilter() {
super(new AntPathRequestMatcher("/login", "POST"));
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String username = this.obtainUsername(request);
String password = this.obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
@Nullable
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(this.passwordParameter);
}
@Nullable
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(this.usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(this.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 this.usernameParameter;
}
public final String getPasswordParameter() {
return this.passwordParameter;
}
}
修改构造器名字为MobileAuthenticationFilter


修改账号密码为获取手机号


修改html请求路径url


修改获取账号密码为获取手机号


模仿UsernamePasswordAuthenticationToken创建MobileAuthenticationToken

修改setDetails方法的UsernamePasswordAuthenticationToken为MobileAuthenticationToken


把账号密码替换成手机号


修改后源码
package com.cis.security.authentication.mobile;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 用于校验用户手机号是否允许通过认证
*/
public class MobileAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
//html表单手机号的name属性名是:mobile
private String mobileParameter = "mobile";
private boolean postOnly = true;
//修改html表单的请求路径url为:/mobile/form"
public MobileAuthenticationFilter() {
super(new AntPathRequestMatcher("/mobile/form", "POST"));
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String mobile = obtainMobile(request);
if (mobile == null) {
mobile = "";
}
mobile = mobile.trim();
MobileAuthenticationToken authRequest = new MobileAuthenticationToken(mobile);
//UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
/**
* 从请求中获取手机号码
*/
@Nullable
protected String obtainMobile(HttpServletRequest request) {
return request.getParameter(mobileParameter);
}
/**
* 将 sessionID和hostname添加 到MobileAuthenticationToken
*/
protected void setDetails(HttpServletRequest request,
MobileAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
/**
* 设置是否为post请求
*/
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public String getMobileParameter() {
return mobileParameter;
}
public void setMobileParameter(String mobileParameter) {
this.mobileParameter = mobileParameter;
}
}

4.创建MobileAuthenticationToken,模仿UsernamePasswordAuthenticationToken
修改前
package com.cis.security.authentication.mobile;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
public class MobileAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 520L;
private final Object principal;
private Object credentials;
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super((Collection)null);
this.principal = principal;
this.credentials = credentials;
this.setAuthenticated(false);
}
public UsernamePasswordAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true);
}
public Object getCredentials() {
return this.credentials;
}
public Object getPrincipal() {
return this.principal;
}
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
} else {
super.setAuthenticated(false);
}
}
public void eraseCredentials() {
super.eraseCredentials();
this.credentials = null;
}
}
修改构造方法


修改账号密码为手机号


修改后源码
package com.cis.security.authentication.mobile;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
public class MobileAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = 520L;
// principal:认证前存的是手机号码,认证后存的是用户信息
private final Object principal;
/**
* 认证之前使用的构造方法, 此方法会标识未认证
*
*/
public MobileAuthenticationToken(Object principal) {
super((Collection)null);
this.principal = principal; // 手机号码
setAuthenticated(false); // 未认证
}
/**
* 认证通过后,会重新创建MobileAuthenticationToken实例 ,来进行封装认证信息
* @param principal 用户信息
* @param authorities 权限资源
*/
public MobileAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;//用户信息
super.setAuthenticated(true); // 已认证
}
/**
* 因为它是父类中的抽象方法,,所以要实现,这里是返回密码,没有密码,直接返回null即可
* @return
*/
@Override
public Object getCredentials() {
return null;
}
//获取用户信息,这里是返回用户信息
public Object getPrincipal() {
return this.principal;
}
//设置权限资源
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
} else {
super.setAuthenticated(false);
}
}
public void eraseCredentials() {
super.eraseCredentials();
}
}
|