SpringSecurity实现自定义登录方式

 更新时间:2024年09月18日 10:06:26   作者:勿语&  
本文介绍自定义登录流程,包括自定义AuthenticationToken、AuthenticationFilter、AuthenticationProvider以及SecurityConfig配置类,详细解析了认证流程的实现,为开发人员提供了具体的实施指导和参考

自定义登录

  • 定义Token
  • 定义Filter
  • 定义Provider
  • 配置类中定义登录的接口

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);
    }
}

2.自定义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));
    }
}

3.自定义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);
    }
}

4.定义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();
        };
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot Knife4j框架&Knife4j的显示内容的配置方式

    SpringBoot Knife4j框架&Knife4j的显示内容的配置方式

    Knife4j框架是基于Swagger2开发的在线API文档生成工具,主要功能包括自动生成API文档、接口文档展示、接口测试工具、接口权限控制和在线调试,该框架支持通过注解自动生成详细的接口文档,开发者可以直接在文档界面进行接口测试和调试
    2024-09-09
  • java8 Stream大数据量List分批处理切割方式

    java8 Stream大数据量List分批处理切割方式

    这篇文章主要介绍了java8 Stream大数据量List分批处理切割方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 使用AOP拦截Controller获取@PathVariable注解传入的参数

    使用AOP拦截Controller获取@PathVariable注解传入的参数

    这篇文章主要介绍了使用AOP拦截Controller获取@PathVariable注解传入的参数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 如何使用Java 8 中的 Stream 遍历树形结构

    如何使用Java 8 中的 Stream 遍历树形结构

    这篇文章主要介绍了使用Java 8中的Stream遍历树形结构,我们可以使用Java8中的Stream流一次性把数据查出来,然后通过流式处理,我们一起来看看,代码实现为了实现简单,就模拟查看数据库所有数据到List里面,需要的朋友可以参考下
    2023-08-08
  • java web实现简单留言板功能

    java web实现简单留言板功能

    这篇文章主要为大家详细介绍了java web实现简单留言板功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • springboot 正确的在异步线程中使用request的示例代码

    springboot 正确的在异步线程中使用request的示例代码

    这篇文章主要介绍了springboot中如何正确的在异步线程中使用request,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • java实现递归菜单树

    java实现递归菜单树

    这篇文章主要为大家详细介绍了java实现递归菜单树,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08
  • Java多线程中Lock锁的使用小结

    Java多线程中Lock锁的使用小结

    这篇文章主要介绍了Java多线程中Lock锁的使用小结,本节主要讲了它的基本使用,大家可以举一反三,试试什么条件下会导致死锁,需要的朋友可以参考下
    2022-06-06
  • Java结构性设计模式中的装饰器模式介绍使用

    Java结构性设计模式中的装饰器模式介绍使用

    装饰器模式又名包装(Wrapper)模式。装饰器模式以对客户端透明的方式拓展对象的功能,是继承关系的一种替代方案,本篇文章以虹猫蓝兔生动形象的为你带来详细讲解
    2022-09-09
  • Java concurrency之Condition条件_动力节点Java学院整理

    Java concurrency之Condition条件_动力节点Java学院整理

    Condition的作用是对锁进行更精确的控制。下面通过本文给大家分享Java concurrency之Condition条件的相关知识,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-06-06

最新评论