SpringSecurity自定义登录方式

自定义登录:

  1. 定义Token
  2. 定义Filter
  3. 定义Provider
  4. 配置类中定义登录的接口
  1. 自定义AuthenticationToken
public class EmailAuthenticationToken extends UsernamePasswordAuthenticationToken{

    public EmailAuthenticationToken(Object principal, Object credentials) {
        super(principal, credentials);
    }

    public EmailAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(principal, credentials, authorities);
    }
}

  1. 自定义AuthenticationFilter
public class EmailAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    private static final String EMAIL = "email";
    private static final String EMAIL_CODE = "emailCode";
    private boolean postOnly = true;


    public EmailAuthenticationFilter(RequestMatcher requestMatcher) {
        super(requestMatcher);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {
            Map<String, String> map = new ObjectMapper().readValue(request.getInputStream(), Map.class);
            String email = map.get(EMAIL);
            email = email != null ? email : "";
            email = email.trim();
            String emailCode = map.get(EMAIL_CODE);
            emailCode = emailCode != null ? emailCode : "";
            EmailAuthenticationToken emailAuthenticationToken = new EmailAuthenticationToken(email, emailCode);
            this.setDetails(request, emailAuthenticationToken);
            return this.getAuthenticationManager().authenticate(emailAuthenticationToken);
        }
    }

    protected void setDetails(HttpServletRequest request, EmailAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }
}
  1. 自定义AuthenticationProvider
public class EmailAuthenticationProvider implements AuthenticationProvider {
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        EmailAuthenticationToken emailAuthenticationToken = (EmailAuthenticationToken) authentication;
        String code = emailAuthenticationToken.getCode();
        String email = (String) emailAuthenticationToken.getPrincipal();
        if (email.equals("205564122@qq.com") && code.equals("1234")) {
            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("wuyu");
            return new EmailAuthenticationToken(email, null, List.of(simpleGrantedAuthority));
        }
        throw new InternalAuthenticationServiceException("认证失败");
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return EmailAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

  1. 定义SecurityConfig配置类
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.cors().disable();
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.authorizeHttpRequests().anyRequest().permitAll();
        http.logout().logoutSuccessHandler(logoutSuccessHandler());

        // 配置邮箱登录
        EmailAuthenticationFilter emailAuthenticationFilter = new EmailAuthenticationFilter(new AntPathRequestMatcher("/login/email", "POST"));
        emailAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
        emailAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler());
        emailAuthenticationFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
        http.addFilterBefore(emailAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
        http.authenticationProvider(new EmailAuthenticationProvider());
    }

    @Bean
    public AuthenticationSuccessHandler authenticationSuccessHandler() {
        return (request, response, authentication) -> {
            // 1.生成Token
            String token = UUID.randomUUID().toString();
            // 2.将Token和用户信息存入redis
            stringRedisTemplate.opsForValue().set(AuthConstants.TOKEN_PREFIX + token, JSON.toJSONString(authentication.getPrincipal()), AuthConstants.TOKEN_DURATION);
            // 3.返回Token
            response.setContentType(ResponseConstants.APPLICATION_JSON);
            PrintWriter writer = response.getWriter();
            writer.write(JSON.toJSONString(Result.success(token)));
            writer.flush();
            writer.close();
        };
    }

    @Bean
    public AuthenticationFailureHandler authenticationFailureHandler() {
        return (request, response, exception) -> {
            response.setContentType(ResponseConstants.APPLICATION_JSON);
            PrintWriter writer = response.getWriter();
            writer.write(JSON.toJSONString(Result.fail(exception.getMessage())));
            writer.flush();
            writer.close();
        };
    }

    @Bean
    public LogoutSuccessHandler logoutSuccessHandler() {
        return (request, response, authentication) -> {
            String authorization = request.getHeader(AuthConstants.AUTHORIZATION);
            authorization = authorization.replace(AuthConstants.BEARER, "");
            stringRedisTemplate.delete(AuthConstants.TOKEN_PREFIX + authorization);
            PrintWriter writer = response.getWriter();
            writer.write(JSON.toJSONString(Result.success()));
            writer.flush();
            writer.close();
        };
    }
}

### 回答1: Spring Security提供了多种登录方式的支持,可以使用表单登录、Basic认证、OAuth2等方式进行身份验证。如果需要自定义多种登录方式,可以按照以下步骤进行: 1. 实现自定义的AuthenticationProvider AuthenticationProvider是Spring Security的一个核心接口,用于实现身份验证逻辑。通过实现自定义的AuthenticationProvider,可以实现多种不同的身份验证方式。 例如,可以实现一个LDAPAuthenticationProvider,用于基于LDAP的身份验证,或者实现一个SmsCodeAuthenticationProvider,用于基于短信验证码的身份验证。 2. 配置多个AuthenticationProvider 在Spring Security的配置文件中,可以通过配置多个AuthenticationProvider来支持多种登录方式。例如,可以同时配置一个基于表单登录的AuthenticationProvider和一个基于OAuth2的AuthenticationProvider。 3. 实现自定义的AuthenticationFilter AuthenticationFilter是Spring Security用于处理身份验证请求的过滤器。通过实现自定义的AuthenticationFilter,可以实现多种不同的身份验证方式。 例如,可以实现一个基于短信验证码的AuthenticationFilter,用于处理短信验证码登录请求。 4. 配置多个AuthenticationFilter 在Spring Security的配置文件中,可以通过配置多个AuthenticationFilter来支持多种登录方式。例如,可以同时配置一个基于表单登录的AuthenticationFilter和一个基于短信验证码的AuthenticationFilter。 总的来说,实现多种登录方式的关键在于实现自定义的AuthenticationProvider和AuthenticationFilter,并在Spring Security的配置文件中进行配置。 ### 回答2: Spring Security 提供了多种自定义登录方式的选项。以下是一些常见的方法: 1. 自定义用户名密码登录:可以使用 Spring Security 的表单登录功能,通过配置用户名和密码的输入框,实现用户名密码登录功能。 例如,可以通过配置 `formLogin()` 方法来实现: ```java protected void configure(HttpSecurity http) throws Exception { http .formLogin() .loginPage("/login") .usernameParameter("username") .passwordParameter("password") .defaultSuccessUrl("/home") .permitAll(); } ``` 2. 自定义第三方登录:可以使用 Spring Security OAuth2 来实现第三方登录,例如使用 Facebook、Google 或 Github 等社交媒体的账号进行登录Spring Security OAuth2 提供了很多集成第三方认证的实例代码,可以根据具体的需求进行自定义。 3. 自定义手机号码登录:可以通过继承 Spring Security 的 `AbstractAuthenticationProcessingFilter` 类来实现自定义手机号码登录。 可以在自定义的过滤器中验证手机号码,并进行认证逻辑。 4. 自定义单点登录(SSO):可以通过集成 Spring Security 的 `AuthenticationProvider` 接口来实现自定义的单点登录认证。 可以通过实现该接口的 `authenticate()` 方法来处理单点登录的逻辑。 这些只是一些常见的自定义登录方式的示例,根据具体的需求,可以结合 Spring Security 提供的各种功能和扩展点,灵活地进行自定义实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值