spring security 一个验证码登录例子

青旅半醒 2022-05-28 10:59 294阅读 0赞

看完shiro,在看spring security感觉快了很多,最开始看spring security的时候,非常晕,看完我觉得spring security做了太多事,以至于程序员都不知道,是怎么实现的,这样的

后果就是 当出现错误,或者需要修改的时候感觉无从下手。

个人理解,若有错误,请指正。

spring security跟shiro类似,都是使用过滤器来认证和授权,不同的是spring seciruty是实现了一个过滤器链,每个请求都要经过,我们可以使用自动配置,这样spring security自动帮我们配置了这一系列过滤器,也可以自定义过滤器放在它的过滤器链中。

验证码或密码登录,需要重新修改认证过滤器

[java] view plain copy

  1. package com.test.hello.security;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;
  4. import org.springframework.security.authentication.AbstractAuthenticationToken;
  5. import org.springframework.security.authentication.AuthenticationServiceException;
  6. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  7. import org.springframework.security.core.Authentication;
  8. import org.springframework.security.core.AuthenticationException;
  9. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
  10. public class KdUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
  11. private boolean postOnly = true;
  12. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
  13. if (this.postOnly && !request.getMethod().equals(“POST”)) {
  14. throw new AuthenticationServiceException(“Authentication method not supported: “ + request.getMethod());
  15. }
  16. String username = obtainUsername(request);
  17. String password = obtainPassword(request);
  18. String type = request.getParameter(“j_type”);
  19. if (username == null) {
  20. username = “”;
  21. }
  22. if (password == null) {
  23. password = “”;
  24. }
  25. if (type == null) {
  26. type = “1”;
  27. }
  28. username = username.trim();
  29. Authentication authRequest;
  30. if(type.equals(“1”)){
  31. authRequest = new UsernamePasswordAuthenticationToken(username, password);
  32. }else{
  33. authRequest = new KdUsernamePasswordAuthenticationToken(username, password,type);
  34. }
  35. // Allow subclasses to set the “details” property
  36. setDetails(request, (AbstractAuthenticationToken)authRequest);
  37. return this.getAuthenticationManager().authenticate(authRequest);
  38. }
  39. /**
  40. * Provided so that subclasses may configure what is put into the authentication request’s details
  41. * property.
  42. *
  43. * @param request that an authentication request is being created for
  44. * @param authRequest the authentication request object that should have its details set
  45. */
  46. protected void setDetails(HttpServletRequest request, AbstractAuthenticationToken authRequest) {
  47. authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
  48. }
  49. }

type为2时候,使用验证码登录,token- >provider ->

token

[java] view plain copy

  1. package com.test.hello.security;
  2. import java.util.Collection;
  3. import org.springframework.security.authentication.AbstractAuthenticationToken;
  4. import org.springframework.security.core.GrantedAuthority;
  5. public class KdUsernamePasswordAuthenticationToken extends AbstractAuthenticationToken{
  6. //~ Instance fields ================================================================================================
  7. /**
  8. *
  9. */
  10. private static final long serialVersionUID = 1L;
  11. private final Object principal;
  12. private Object credentials;
  13. private String type;
  14. //~ Constructors ===================================================================================================
  15. /**
  16. * This constructor can be safely used by any code that wishes to create a
  17. * UsernamePasswordAuthenticationToken, as the {@link
  18. * #isAuthenticated()} will return false.
  19. *
  20. */
  21. public KdUsernamePasswordAuthenticationToken(Object principal, Object credentials,String type) {
  22. super(null);
  23. this.principal = principal;
  24. this.credentials = credentials;
  25. this.type = type;
  26. setAuthenticated(false);
  27. }
  28. /**
  29. * This constructor should only be used by AuthenticationManager or AuthenticationProvider
  30. * implementations that are satisfied with producing a trusted (i.e. {@link #isAuthenticated()} = true)
  31. * authentication token.
  32. *
  33. * @param principal
  34. * @param credentials
  35. * @param authorities
  36. */
  37. public KdUsernamePasswordAuthenticationToken(Object principal, Object credentials,String type, Collection<? extends GrantedAuthority> authorities) {
  38. super(authorities);
  39. this.principal = principal;
  40. this.credentials = credentials;
  41. this.type = type;
  42. super.setAuthenticated(true); // must use super, as we override
  43. }
  44. //~ Methods ========================================================================================================
  45. public Object getCredentials() {
  46. return this.credentials;
  47. }
  48. public Object getPrincipal() {
  49. return this.principal;
  50. }
  51. public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
  52. if (isAuthenticated) {
  53. throw new IllegalArgumentException(
  54. “Once created you cannot set this token to authenticated. Create a new instance using the constructor which takes a GrantedAuthority list will mark this as authenticated.”);
  55. }
  56. super.setAuthenticated(false);
  57. }
  58. @Override
  59. public void eraseCredentials() {
  60. super.eraseCredentials();
  61. credentials = null;
  62. }
  63. public String getType() {
  64. return type;
  65. }
  66. public void setType(String type) {
  67. this.type = type;
  68. }
  69. }

provider 重写了 密码校验方法,并且默认使用了KdJdbcDaoImpl去查询用户信息

KdAbstractUserDetailsAuthenticationProvider跟AbstractUserDetailsAuthenticationProvider一样仅仅改了authenticate方法里面的

Assert.isInstanceOf(KdUsernamePasswordAuthenticationToken.class,

[java] view plain copy

  1. package com.test.hello.security;
  2. import org.springframework.security.authentication.BadCredentialsException;
  3. import org.springframework.security.authentication.InternalAuthenticationServiceException;
  4. import org.springframework.security.core.AuthenticationException;
  5. import org.springframework.security.core.userdetails.UserDetails;
  6. import org.springframework.security.core.userdetails.UserDetailsService;
  7. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  8. public class KdDaoAuthenticationProvider extends KdAbstractUserDetailsAuthenticationProvider{
  9. private UserDetailsService userDetailsService = new KdJdbcDaoImpl();
  10. public UserDetailsService getUserDetailsService() {
  11. return userDetailsService;
  12. }
  13. public void setUserDetailsService(UserDetailsService userDetailsService) {
  14. this.userDetailsService = userDetailsService;
  15. }
  16. @Override
  17. public boolean supports(Class<?> authentication) {
  18. return (KdUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
  19. }
  20. @SuppressWarnings(“deprecation”)
  21. @Override
  22. protected void additionalAuthenticationChecks(UserDetails userDetails,
  23. KdUsernamePasswordAuthenticationToken authentication)
  24. throws AuthenticationException {
  25. if (authentication.getCredentials() == null) {
  26. logger.debug(“Authentication failed: no credentials provided”);
  27. throw new BadCredentialsException(messages.getMessage(
  28. “AbstractUserDetailsAuthenticationProvider.badCredentials”, “Bad credentials”), userDetails);
  29. }
  30. String presentedPassword = authentication.getCredentials().toString();
  31. if (!userDetails.getPassword().equals(presentedPassword)) {
  32. logger.debug(“Authentication failed: password does not match stored value”);
  33. throw new BadCredentialsException(messages.getMessage(
  34. “AbstractUserDetailsAuthenticationProvider.badCredentials”, “Bad credentials”), userDetails);
  35. }else{
  36. KdJdbcDaoImpl.userpass.remove(userDetails.getUsername());
  37. }
  38. }
  39. @Override
  40. protected UserDetails retrieveUser(String username,
  41. KdUsernamePasswordAuthenticationToken authentication)
  42. throws AuthenticationException {
  43. UserDetails loadedUser;
  44. try {
  45. loadedUser = this.getUserDetailsService().loadUserByUsername(username);
  46. } catch (UsernameNotFoundException notFound) {
  47. throw notFound;
  48. } catch (Exception repositoryProblem) {
  49. throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
  50. }
  51. if (loadedUser == null) {
  52. throw new InternalAuthenticationServiceException(
  53. “UserDetailsService returned null, which is an interface contract violation”);
  54. }
  55. return loadedUser;
  56. }
  57. }

KdJdbcDaoImpl

[java] view plain copy

  1. package com.test.hello.security;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.concurrent.ConcurrentHashMap;
  5. import org.springframework.security.core.authority.AuthorityUtils;
  6. import org.springframework.security.core.userdetails.User;
  7. import org.springframework.security.core.userdetails.UserDetails;
  8. import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
  9. public class KdJdbcDaoImpl extends JdbcDaoImpl{
  10. public static ConcurrentHashMap userpass = new ConcurrentHashMap();
  11. @Override
  12. protected List loadUsersByUsername(String username) {
  13. List list = new ArrayList();
  14. String password = userpass.get(username);
  15. if(password != null){
  16. list.add(new User(username, password, true, true, true, true, AuthorityUtils.NO_AUTHORITIES));
  17. }
  18. return list;
  19. }
  20. }

最后的配置

[java] view plain copy

[java] view plain copy

  1. <%@ page language=”java” import=”java.util.*“ pageEncoding=”UTF-8”%>
  2. <%
  3. String path = request.getContextPath();
  4. String basePath = request.getScheme()+”://“+request.getServerName()+”:”+request.getServerPort()+path+”/“;
  5. %>
  6. <%@ taglib uri=”http://java.sun.com/jsp/jstl/core“ prefix=”c”%>
  7. <!DOCTYPE html PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd">
  8. My JSP ‘index.jsp’ starting page
  9. This is my login page.
  10. 用户名:
    密码/验证码:
    登录方式:
  11. 异常: ${SPRING_SECURITY_LAST_EXCEPTION }
  12. 失败次数: ${SPRING_SESSION_FAIL_TIMES }

发表评论

表情:
评论列表 (有 0 条评论,294人围观)

还没有评论,来说两句吧...

相关阅读