spring security4 添加验证码的示例代码
|
spring security是一个很大的模块,本文中只涉及到了自定义参数的认证。spring security默认的验证参数只有username和password,一般来说都是不够用的。由于时间过太久,有些忘,可能有少许遗漏。好了,不废话。 首先定义EntryPoint:
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint {
public MyAuthenticationEntryPoint(String loginFormUrl) {
super(loginFormUrl);
}
@Override
public void commence(HttpServletRequest request,HttpServletResponse response,AuthenticationException authException) throws IOException,ServletException {
super.commence(request,response,authException);
}
}
接下来是token,validCode是验证码参数:
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
public class MyUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken {
private String validCode;
public MyUsernamePasswordAuthenticationToken(String principal,String credentials,String validCode) {
super(principal,credentials);
this.validCode = validCode;
}
public String getValidCode() {
return validCode;
}
public void setValidCode(String validCode) {
this.validCode = validCode;
}
}
继续ProcessingFilter,
import com.core.shared.ValidateCodeHandle;
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 javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class MyValidCodeProcessingFilter extends AbstractAuthenticationProcessingFilter {
private String usernameParam = "username";
private String passwordParam = "password";
private String validCodeParam = "validateCode";
public MyValidCodeProcessingFilter() {
super(new AntPathRequestMatcher("/user/login","POST"));
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException,IOException,ServletException {
String username = request.getParameter(usernameParam);
String password = request.getParameter(passwordParam);
String validCode = request.getParameter(validCodeParam);
valid(validCode,request.getSession());
MyUsernamePasswordAuthenticationToken token = new MyUsernamePasswordAuthenticationToken(username,password,validCode);
return this.getAuthenticationManager().authenticate(token);
}
public void valid(String validCode,HttpSession session) {
if (validCode == null) {
throw new ValidCodeErrorException("验证码为空!");
}
if (!ValidateCodeHandle.matchCode(session.getId(),validCode)) {
throw new ValidCodeErrorException("验证码错误!");
}
}
}
分别定义三个参数,用于接收login表单过来的参数,构造方法给出了login的url以及需要post方式 接下来就是认证了,此处还没到认证用户名和密码的时候,只是认证了验证码 下面是ValidateCodeHandle一个工具类以及ValidCodeErrorException:
import java.util.concurrent.ConcurrentHashMap;
public class ValidateCodeHandle {
private static ConcurrentHashMap validateCode = new ConcurrentHashMap<>();
public static ConcurrentHashMap getCode() {
return validateCode;
}
public static void save(String sessionId,String code) {
validateCode.put(sessionId,code);
}
public static String getValidateCode(String sessionId) {
Object obj = validateCode.get(sessionId);
if (obj != null) {
return String.valueOf(obj);
}
return null;
}
public static boolean matchCode(String sessionId,String inputCode) {
String saveCode = getValidateCode(sessionId);
if (saveCode.equals(inputCode)) {
return true;
}
return false;
}
}
这里需要继承AuthenticationException以表明它是security的认证失败,这样才会走后续的失败流程
import org.springframework.security.core.AuthenticationException;
public class ValidCodeErrorException extends AuthenticationException {
public ValidCodeErrorException(String msg) {
super(msg);
}
public ValidCodeErrorException(String msg,Throwable t) {
super(msg,t);
}
}
接下来是Provider:
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
public class MyAuthenticationProvider extends DaoAuthenticationProvider {
@Override
public boolean supports(Class<?> authentication) {
return MyUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
Object salt = null;
if (getSaltSource() != null) {
salt = getSaltSource().getSalt(userDetails);
}
if (authentication.getCredentials() == null) {
logger.debug("Authentication failed: no credentials provided");
throw new BadCredentialsException("用户名或密码错误!");
}
String presentedPassword = authentication.getCredentials().toString();
if (!this.getPasswordEncoder().isPasswordValid(userDetails.getPassword(),presentedPassword,salt)) {
logger.debug("Authentication failed: password does not match stored value");
throw new BadCredentialsException("用户名或密码错误!");
}
}
}
其中supports方法指定使用自定义的token,additionalAuthenticationChecks方法和父类的逻辑一模一样,我只是更改了异常返回的信息。 接下来是处理认证成功和认证失败的handler
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class FrontAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public FrontAuthenticationSuccessHandler(String defaultTargetUrl) {
super(defaultTargetUrl);
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request,Authentication authentication) throws IOException,ServletException {
super.onAuthenticationSuccess(request,authentication);
}
}
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class FrontAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
public FrontAuthenticationFailureHandler(String defaultFailureUrl) {
super(defaultFailureUrl);
}
@Override
public void onAuthenticationFailure(HttpServletRequest request,AuthenticationException exception) throws IOException,ServletException {
super.onAuthenticationFailure(request,exception);
}
}
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
