SpringSceurity实现短信验证码功能的示例代码

下面我将详细讲解如何使用Spring Security实现短信验证码功能。这里假设你已经有了一个基于Spring Security的Web应用程序,现在要添加短信验证码功能。

准备工作

在开始实现之前需要进行一些准备工作:

1.添加Spring Security支持短信验证码功能的依赖;

pom.xml中添加以下依赖:

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-servlet</artifactId>
    <version>${spring.security.version}</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2.配置短信验证码发送的相关信息;

可以使用Spring的@Configuration注解创建一个Bean来配置短信验证码发送的相关信息,例如短信网关地址、短信模板等。

实现

下面将分步骤来实现Spring Security中的短信验证码功能。

步骤1:创建一个用于发送短信验证码的服务

可以使用Spring的@Component注解创建一个短信发送服务的Bean。

@Component
public class SmsCodeSender {

    @Autowired
    private SmsCodeProperties smsCodeProperties;

    private final static Logger logger = LoggerFactory.getLogger(SmsCodeSender.class);

    public void sendSmsCode(String mobile, String code) {
        // 发送短信验证码的代码
    }
}

步骤2:编写一个生成短信验证码的过滤器

可以使用Spring的OncePerRequestFilter来过滤需要生成短信验证码的请求。

public class SmsCodeFilter extends OncePerRequestFilter {

    @Autowired
    private SmsCodeSender smsCodeSender;

    @Autowired
    private SmsCodeProperties smsCodeProperties;

    private AntPathMatcher pathMatcher = new AntPathMatcher();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if ("POST".equalsIgnoreCase(request.getMethod()) && pathMatcher.match("/login/mobile", request.getServletPath())) {
            try {
                validate(new ServletWebRequest(request));
            } catch (ValidationException e) {
                // 验证失败,返回错误信息
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("验证码错误或已过期!");
            }
        } else {
            filterChain.doFilter(request, response);
        }
    }

    private void validate(ServletWebRequest request) {
        String mobile = request.getParameter("mobile");
        String smsCode = request.getParameter("smsCode");

        // 从Session中获取短信验证码
        String codeInSession = (String) request.getRequest().getSession().getAttribute(SmsCodeController.SESSION_KEY_SMS_CODE + mobile);

        if (StringUtils.isBlank(smsCode)) {
            throw new ValidationException("验证码不能为空!");
        }

        if (codeInSession == null) {
            throw new ValidationException("验证码不存在!");
        }

        if (!StringUtils.equals(codeInSession, smsCode)) {
            throw new ValidationException("验证码不正确!");
        }

        request.getRequest().getSession().removeAttribute(SmsCodeController.SESSION_KEY_SMS_CODE + mobile);
    }

}

步骤3:配置短信验证码过滤器

需要在Spring Security过滤器链中添加自定义的短信验证码过滤器,以便拦截需要验证短信验证码的请求。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SmsCodeFilter smsCodeFilter;

    // ...

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login")
                .successForwardUrl("/index")
                .and()
                .authorizeRequests().antMatchers("/login/**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable();
    }
}

步骤4:生成和发送短信验证码

可以使用Spring的@Controller注解创建一个控制器,在控制器中生成和发送短信验证码。

@Controller
@Slf4j
public class SmsCodeController {

    public static final String SESSION_KEY_SMS_CODE = "SESSION_KEY_SMS_CODE:";

    @Autowired
    private SmsCodeSender smsCodeSender;

    @Autowired
    private SmsCodeProperties smsCodeProperties;

    @PostMapping("/code/sms")
    @ResponseBody
    public JsonResponse createSmsCode(HttpServletRequest request, @RequestParam("mobile") String mobile) throws ServletRequestBindingException {
        if (!MobileUtils.isMobile(mobile)) {
            return JsonResponse.error("手机号码格式不正确!");
        }

        // 生成短信验证码
        String code = RandomStringUtils.randomNumeric(6);
        String key = SESSION_KEY_SMS_CODE + mobile;

        request.getSession().setAttribute(key, code);
        request.getSession().setMaxInactiveInterval(smsCodeProperties.getExpireTime());

        // 发送短信验证码
        smsCodeSender.sendSmsCode(mobile, code);
        log.info("手机号 [" + mobile + "] 短信验证码 [" + code + "] 已发送");

        return JsonResponse.ok("短信验证码已发送!");
    }

}

示例1

这个示例的目的是显示一个用于获取验证码的按钮,并添加一个JavaScript函数来调用后端的短信列表。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<form id="login-form" action="/login" method="post" style="padding: 10px;">
    <input type="text" name="mobile" placeholder="电话号码"/>
    <input type="text" name="smsCode" placeholder="短信验证码"/>
    <button id="sms-button" type="button">获取短信验证码</button>
    <button type="submit">登录</button>
</form>

<script>
    $(document).ready(function () {
        $('#sms-button').click(function () {
            $.ajax({
                url: '/code/sms',
                data: {
                    mobile: $('input[name="mobile"]').val()
                },
                success: function (data) {
                    alert(data.message);
                },
                error: function (e) {
                    alert("发生错误!");
                }
            });
        });
    });
</script>
</body>
</html>

在上面的代码中,#sms-button是用于获取验证码的按钮的ID。当用户单击该按钮时,JavaScript将会以GET方法调用/code/sms地址。后端的SmsCodeController将会生成和发送短信验证码。

示例2

一个简单的启用短信验证码功能的Spring Security配置可以是这样的:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private SmsCodeFilter smsCodeFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("/", "/login**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/login")
                .successHandler(new LoginSuccessHandler())
                .failureHandler(new LoginFailureHandler())
                .and()
                .logout()
                .logoutUrl("/logout")
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID")
                .permitAll()
                .and()
                .csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

在上面的示例代码中,除了添加SmsCodeFilter过滤器之外,其他内容都和普通的Spring Security配置一样。例如,/admin/**路径要求用户有ADMIN角色,所有其他请求都需要用户被验证(即登录)。LoginSuccessHandlerLoginFailureHandler是登录成功或失败时将要执行的一些逻辑。关闭CSRF保护是为了使示例变得更加简单,可以在实际项目中开启它。

结论

Spring Security提供了一个灵活和可扩展的框架,可以轻松实现短信验证码功能。使用短信验证码可以提高Web应用程序的安全性,同时也为用户提供更加便捷的登录方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringSceurity实现短信验证码功能的示例代码 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Java JVM内存区域详解

    Java JVM内存区域详解 简介 Java虚拟机(Java Virtual Machine,JVM)是Java语言的核心和基础,是Java实现”一次编写,到处运行”特性的核心。在JVM中,Java程序在运行时会占用不同的内存区域,这些内存区域分别承担着不同的作用,在理解Java程序运行机制时,对这些内存区域有深入的认识很有帮助。 Java JVM内存区域介…

    Java 2023年5月26日
    00
  • Hadoop中的压缩与解压缩案例详解

    下面就为您详细讲解“Hadoop中的压缩与解压缩案例详解”的完整攻略。 什么是Hadoop中的压缩与解压缩? 在Hadoop中,由于数据量通常都很大,为了提高数据的存储效率和运行效率,我们经常需要将数据进行压缩。同时,在MapReduce的过程中,也需要对数据进行解压缩以方便处理。 Hadoop支持多种数据压缩格式,包括Gzip、Bzip2、LZO等。在使用…

    Java 2023年5月20日
    00
  • 浅谈Java 三种方式实现接口校验

    让我来详细讲解一下“浅谈Java 三种方式实现接口校验”的完整攻略。 标题 介绍 接口校验是指在进行接口调用时,对传入参数的合法性进行校验,以避免非法参数对系统造成的危害。Java中有多种实现接口校验的方法,本文将介绍三种常用方式: 使用第三方框架 使用注解方式 使用AOP面向切面编程 第一种:使用第三方框架 如果你对接口校验的要求比较简单,可以考虑使用第三…

    Java 2023年5月20日
    00
  • springBoot集成mybatis 转换为 mybatis-plus方式

    以下是使用springBoot集成mybatis转换为mybatis-plus的完整攻略。 1. 添加mybatis-plus依赖 <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</art…

    Java 2023年5月20日
    00
  • Java实现多文件上传功能

    Java实现多文件上传功能攻略 本文主要介绍如何使用Java来实现多文件上传功能。 1. 前端实现 前端部分我们可以使用HTML表单来实现多文件上传的界面: <form action="/upload" method="post" enctype="multipart/form-data"&g…

    Java 2023年5月19日
    00
  • intellij idea修改maven配置时总是恢复默认配置的解决方法idea版本(2020.2.x)

    针对这个问题,我会提供以下攻略,步骤如下: 1. 确认问题 在修改 Maven 配置时,IntelliJ IDEA 总是恢复默认配置,这可能是由于 IntelliJ IDEA 的配置文件出现了问题。在解决问题之前,需要先确认问题所在,所以可以尝试以下步骤: 步骤一:尝试在另外一个项目中修改配置 在另外一个项目中修改 Maven 配置,查看是否会出现同样的问题…

    Java 2023年5月19日
    00
  • 微信小程序微信登录的实现方法详解(JAVA后台)

    下面是详细的攻略: 背景介绍 微信小程序微信登录是指用户可以通过微信账号快速登录小程序,无需再次注册账号。实现微信登录的关键在于后台服务器实现微信的登录认证功能。本文将详细讲解如何在Java后台实现微信登录的功能。 实现方法 实现微信登录功能的具体步骤如下: 1.前端页面添加微信登录按钮 <button type="primary"…

    Java 2023年5月23日
    00
  • 基于spring mvc请求controller访问方式

    基于Spring MVC请求Controller访问方式的完整攻略 Spring MVC是一种基于Java的Web框架,它可以帮助我们快速开发Web应用程序。在Spring MVC中,我们可以使用Controller来处理请求,并返回响应结果。本文将介绍如何使用Spring MVC请求Controller访问方式,并提供两个示例说明。 步骤一:创建Contr…

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