Spring Security 实现多种登录方式(常规方式外的邮件、手机验证码登录)

Spring Security 实现多种登录方式攻略

Spring Security 作为一个强大的安全框架,支持多种登录方式,包括传统的用户名密码登录、第三方登录、手机短信验证码登录、邮件验证码登录等。本攻略将详细介绍如何使用 Spring Security 实现多种登录方式。

传统的用户名密码登录

传统的用户名密码登录是我们最常见的登录方式,主要涉及以下几个步骤:

  1. 配置 Spring Security 的安全配置类,并指定用户名密码登录接口的 URL。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("{noop}admin")
                .roles("ADMIN");
    }
}
  1. 在 Spring Security 的配置类中,通过 formLogin() 方法启用表单登录,并指定登录页面的 URL。
.formLogin()
.loginPage("/login")
  1. 实现用户认证的逻辑。这里使用的是 InMemoryAuthentication 方式。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
            .withUser("admin")
            .password("{noop}admin")
            .roles("ADMIN");
}
  1. 实现用户授权的逻辑。
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/")
            .permitAll()
            .and()
            .logout()
            .permitAll();
}

手机短信验证码登录

手机短信验证码登录是一种比较流行的登录方式,相比传统的用户名密码登录,它更加方便快捷。手机短信验证码登录主要涉及以下几个步骤:

  1. 配置 Spring Security 的安全配置类,并指定手机号码登录接口的 URL。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/login").permitAll()
                .antMatchers("/sms/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and()
                .apply(smsAuthenticationConfig());
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("{noop}admin")
                .roles("ADMIN");
    }

    private SmsAuthenticationConfig smsAuthenticationConfig() {
        SmsAuthenticationConfig authenticationConfig = new SmsAuthenticationConfig();
        authenticationConfig.setAuthenticationManager(authenticationManagerBean());
        authenticationConfig.setAuthenticationSuccessHandler(new SmsAuthenticationSuccessHandler());
        authenticationConfig.setAuthenticationFailureHandler(new SmsAuthenticationFailureHandler());
        return authenticationConfig;
    }
}
  1. 在 Spring Security 的配置类中,通过 apply() 方法配置短信验证码登录,指定短信验证码登录接口的 URL、短信验证码的有效期、短信验证码的长度等信息。
.apply(smsAuthenticationConfig());
  1. 实现短信验证码认证的逻辑。
public class SmsCodeAuthenticationProvider implements AuthenticationProvider {

    private UserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication;

        UserDetails user = userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal());

        if (user == null) {
            throw new InternalAuthenticationServiceException("无法获取用户信息");
        }

        SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user, user.getAuthorities());

        authenticationResult.setDetails(authenticationToken.getDetails());

        return authenticationResult;
    }

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

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

}
  1. 实现短信验证码授权的逻辑。
public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private String mobileParameter = "mobile";
    private boolean postOnly = true;

    public SmsCodeAuthenticationFilter() {
        super(new AntPathRequestMatcher("/sms/login", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("认证方法不支持:" + request.getMethod());
        }

        String mobile = obtainMobile(request);

        if (mobile == null) {
            mobile = "";
        }

        mobile = mobile.trim();

        SmsCodeAuthenticationToken authenticationToken = new SmsCodeAuthenticationToken(mobile);

        setDetails(request, authenticationToken);

        return this.getAuthenticationManager().authenticate(authenticationToken);
    }

    protected String obtainMobile(HttpServletRequest request) {
        return request.getParameter(mobileParameter);
    }

    protected void setDetails(HttpServletRequest request, SmsCodeAuthenticationToken authenticationToken) {
        authenticationToken.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    public void setMobileParameter(String mobileParameter) {
        this.mobileParameter = mobileParameter;
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

}

示例1:https://github.com/wangeditor/SpringSecurity/blob/main/demo-demo02/demo02-ssm/src/main/java/io/github/wangdaopeng/chapter2/controller/SmsCodeController.java

示例2:https://github.com/bfwg/springboot-jwt-starter/blob/master/src/main/java/com/bfwg/security/auth/SmsCodeAuthenticationProvider.java

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security 实现多种登录方式(常规方式外的邮件、手机验证码登录) - Python技术站

(2)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • Java毕业设计实战之共享租车信息管理系统的实现

    Java毕业设计实战之共享租车信息管理系统的实现 共享租车信息管理系统是一个基于Java的Web应用程序,它的主要作用是对租赁车辆进行管理和查询。本文将详细讲解实现该系统的完整攻略。 系统需求 在开始实现前,需要先明确系统的需求: 用户可以注册账号或使用已有账号登录系统; 用户可以浏览车辆信息,包含车辆图片、基本信息、租赁费用等; 用户可以选择租赁车辆,并提…

    Java 2023年5月24日
    00
  • java编程实现简单的网络爬虫示例过程

    下面是Java编程实现简单的网络爬虫示例过程的完整攻略。 一、什么是网络爬虫 网络爬虫(英文名:Web Crawler),也叫网络蜘蛛,是一种自动抓取万维网信息的程序或者脚本,通过程序模拟浏览器行为获取网页信息。网络爬虫是搜索引擎的核心技术之一,搜索引擎通过它获取互联网信息并建立索引。 二、网络爬虫的基本原理 网络爬虫的基本原理是使用HTTP或者HTTPS协…

    Java 2023年5月18日
    00
  • Java矩阵连乘问题(动态规划)算法实例分析

    下面是详细讲解“Java矩阵连乘问题(动态规划)算法实例分析”的完整攻略。 标题 Java矩阵连乘问题(动态规划)算法实例分析 总述 在计算机科学中,矩阵乘法是一个常见的计算问题。 当需要计算大型矩阵的乘积时,可以使用分治法,但这不是一个好的选择,因为分治法带来的额外开销很多。 在这种情况下,动态规划是解决矩阵连乘问题的最好选择。 步骤 下面是Java实现矩…

    Java 2023年5月19日
    00
  • JSP中param动作的实例详解

    当我们想要把参数传递给 JSP 页面时,param 动作是一种非常有用的方法。通过在 JSP 页面中使用 param 动作,我们可以轻松地向页面中传递参数,这些参数可以来自域对象,例如 request、session 或 application,也可以来源于页面 URL 中的查询字符串或表单提交。本文将为大家深入详解 param 动作的用法,通过两个实例帮助…

    Java 2023年6月15日
    00
  • SpringSecurity怎样使用注解控制权限

    使用注解控制权限是Spring Security中比较方便的一种方式。在Spring Security中,我们可以使用@PreAuthorize和@PostAuthorize注解来控制方法的访问权限,以保证系统的安全性。 @PreAuthorize注解 @PreAuthorize注解的作用是在方法执行前进行权限验证,如果验证失败,则该方法不会被执行。该注解的…

    Java 2023年5月20日
    00
  • Java仿12306图片验证码

    下面我会详细讲解“Java仿12306图片验证码”的实现攻略。 简介 图片验证码是一种常用的验证码类型,它可以有效防止机器人恶意攻击。在Java Web应用中,实现验证码功能可以采用Kaptcha、JCaptcha等开源组件,也可以自己编写代码实现。 本文主要介绍如何使用Java编写代码实现仿12306的图片验证码。 实现过程 1. 随机生成验证码字符串 首…

    Java 2023年6月15日
    00
  • Spring boot基于JPA访问MySQL数据库的实现

    让我来给你讲解一下如何使用Spring Boot基于JPA访问MySQL数据库的实现以及示例。整个攻略将分为以下几个步骤: 创建一个Spring Boot项目 添加依赖 配置application.properties 建立实体类 建立Repository 建立Service 建立Controller 运行项目 下面是各个步骤的详细讲解: 1. 创建一个Sp…

    Java 2023年5月20日
    00
  • Java批量写入文件和下载图片的示例代码

    下面是Java批量写入文件和下载图片的完整攻略。 1. 批量写入文件 在Java中批量写入文件可以使用BufferedWriter类和FileWriter类,将要写入文件的内容先存储在一个列表中,然后逐个写入到文件中。以下是示例: import java.io.BufferedWriter; import java.io.FileWriter; import…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部