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 易懂易用的MD5加密(可直接运行)(2)

    下面是完整的攻略: Java易懂易用的MD5加密(可直接运行)(2) 背景信息 本篇攻略是 “Java易懂易用的MD5加密(可直接运行)(1)” 的续篇,如需了解更多背景信息请先查阅前篇攻略。 攻略步骤 1. 导入依赖包 首先,我们需要先导入依赖包。在本篇攻略中,我们使用的是commons-codec依赖包,该包中包含了Java中常用的摘要算法、编码器和哈希…

    Java 2023年6月15日
    00
  • IntelliJ IDEA中配置Tomcat超详细教程

    下面就介绍一下在 IntelliJ IDEA 中配置 Tomcat 并部署 Web 应用的详细步骤: 1. 下载并安装 Tomcat 首先,我们需要从 Apache Tomcat 的官网(https://tomcat.apache.org/)下载 Tomcat,下载完后按照说明安装即可。 2. 创建 Web 项目 在 IntelliJ IDEA 中创建一个新…

    Java 2023年6月3日
    00
  • 常见的垃圾回收算法有哪些?

    以下是关于常见的垃圾回收算法的完整使用攻略: 常见的垃圾回收算法有哪些? 垃圾回收算法指在垃圾回收过程中,如何判断哪些内存空间是垃圾,哪些内存空间是可用的。常见的垃圾回收算法有以下几种: 1. 引用计数算法 引用计数算法是一种简单的垃圾回收算法,它通过计算每个对象被引用的次数来判断对象是否为垃圾。当一个对象的引用计数为0时,就可以将其回收。引用计数算法的优点…

    Java 2023年5月12日
    00
  • SpringBoot+Spring Security无法实现跨域的解决方案

    为了解决Spring Boot + Spring Security无法实现跨域问题,我们可以采取以下步骤: 1. 添加依赖 首先,在pom.xml中添加以下依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>sprin…

    Java 2023年5月20日
    00
  • Java将微信和支付宝支付的个二维码合二为一的方法

    Java将微信支付和支付宝支付的个二维码合二为一的方法可以通过以下步骤实现: 1. 获取二维码图片 首先,需要通过微信和支付宝的API分别获取到需要合并的二维码图片。 微信支付二维码获取示例 // 构造请求 WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); request.s…

    Java 2023年5月23日
    00
  • Java经典用法总结(二)

    让我们来详细讲解一下《Java经典用法总结(二)》的完整攻略。 简介 本文是《Java经典用法总结》系列的第二篇,主要介绍了Java集合类中常用的几种容器及其使用方法,以及常见的集合操作方式和优化。 Java集合类 Java集合类可以被看作是一种数据结构的封装,用于存储一组相关的数据。Java集合类提供了丰富的操作和算法,可以快速对数据进行处理。 Java集…

    Java 2023年5月20日
    00
  • java的Jackson将json字符串转换成泛型List

    转换JSON字符串成Java对象是Java程序中经常需要做的一个任务。有很多开源库能够帮助我们完成这一任务,如Jackson。Jackson 是一个高效的 JSON 处理器,能够将 JSON 字符串解析成 Java 对象。 Jackson 支持将 JSON 转换成 Java 对象,也支持将 JSON 转换成泛型 List,本篇攻略将介绍 Jackson 将 …

    Java 2023年5月26日
    00
  • 剖析Java中的事件处理与异常处理机制

    剖析Java中的事件处理与异常处理机制 事件处理机制 Java中的事件处理机制是一种将某些动作(例如按钮点击、鼠标移动等)与一些代码相结合的机制。具体来说,Java使用了一种称为“观察者设计模式”的方法来实现事件处理。在这种模式中,一个对象(称为“主题”)维护了一组观察者,这些观察者都希望跟踪主题的状态。当主题状态发生变化时,它将会通知所有的观察者,使得它们…

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