springsecurity集成kaptcha功能

news/2024/12/21 23:36:07/

前端代码

本次采用简单的html静态页面作为演示,也可结合vue前后端分离开发,复制就可运行测试

项目目录

登录界面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><script type="text/javascript">function refresh() {document.getElementById('captcha_img').src="/kaptcha?"+Math.random();}</script>
</head>
<body>
<form action="/login" method="post">账号:<input type="text" placeholder="请输入账号" name="username"><br>密码:<input type="password" placeholder="请输入密码" name="password"><br>验证码:  <input type="text" placeholder="请输入验证码" name="code"><div class="item-input"><img id="captcha_img" alt="点击更换" title="点击更换"onclick="refresh()" src="/kaptcha" /></div>记住我:<input type="checkbox" name="remember-me" value="true"><br><input type="submit" value="提交"/>
</form>
</body>
</html>

登录成功

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
成功<a href="/logout">退出</a>
</body>
</html>

后端代码

pom

    <dependencies><!--web--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--图形验证码--><dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version></dependency><!--security--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency><!--数据库--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency></dependencies>

配置类

kaptcha配置类用于生成验证码格式

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Properties;@Configuration
public class KaptchaConfiguration {@Beanpublic DefaultKaptcha getDefaultKaptcha() {com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha();Properties properties = new Properties();properties.put("kaptcha.textproducer.char.string", "0123456789");properties.put("kaptcha.border", "no");properties.put("kaptcha.textproducer.font.color", "black");properties.put("kaptcha.textproducer.char.space", "5");properties.put("kaptcha.textproducer.char.length","4");properties.put("kaptcha.image.height","34");properties.put("kaptcha.textproducer.font.size","30");properties.setProperty("kaptcha.image.width", "164");properties.setProperty("kaptcha.image.height", "64");properties.put("kaptcha.noise.impl","com.google.code.kaptcha.impl.NoNoise");Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}}

springsecurity

import com.sfy.kapcha.filter.CodeFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate DataSource dataSource;@AutowiredPersistentTokenRepository persistentTokenRepository;@Beanpublic PasswordEncoder getPw(){return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 基于内存存储的多用户auth.inMemoryAuthentication().withUser("admin").password(getPw().encode("123")).roles("root");}@Overridepublic void configure(WebSecurity web) throws Exception {// 忽略静态请求web.ignoring().antMatchers("/img/**", "/js/**");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin()//当发现是login时认为是登录,必须和表单提供的地址一致去执行UserDetailsServiceImpl.loginProcessingUrl("/login")//自定义登录界面.loginPage("/login.html").successForwardUrl("/toMain").permitAll().and().addFilterBefore(new CodeFilter(), UsernamePasswordAuthenticationFilter.class);//认证授权http.authorizeRequests().antMatchers("/kaptcha").permitAll()//登录放行不需要认证.antMatchers("/login.html").permitAll()//所有请求都被拦截类似于mvc必须登录后访问.anyRequest().authenticated();//关闭csrf防护http.csrf().disable();//退出登录http.logout().logoutSuccessUrl("/login.html");//记住我http.rememberMe().tokenValiditySeconds(60);}@Beanpublic AuthenticationManager authenticationManagerBean()throws Exception {return super.authenticationManagerBean();}@Beanpublic PersistentTokenRepository getPersistentTokenRepository(){JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();jdbcTokenRepository.setDataSource(dataSource);//第一次启动时建表,第二次使用时注释掉//jdbcTokenRepository.setCreateTableOnStartup(true);return jdbcTokenRepository;}
}

controller

kaptcha

import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;/*** @Author: sfy* @Date: 2024/1/18 11:13*/@RestController
public class KapchaController {@AutowiredDefaultKaptcha defaultKaptcha;@GetMapping("/kaptcha")public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpSession session = request.getSession();response.setDateHeader("Expires", 0);response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");response.addHeader("Cache-Control", "post-check=0, pre-check=0");response.setHeader("Pragma", "no-cache");response.setContentType("image/jpeg");// 创建验证码String capText = defaultKaptcha.createText();// 验证码放入sessionsession.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);BufferedImage bi = defaultKaptcha.createImage(capText);ServletOutputStream out = response.getOutputStream();ImageIO.write(bi, "jpg", out);try {out.flush();} finally {out.close();}}}

 login进行简单的页面重定向(要用Controller)

@Controller
public class LoginController {@RequestMapping("/toMain")public String toMain(){return "redirect:main.html";}}

filter

用于检测图像验证码的正确性,只有当验证码正确时,过滤器链才会走到springsecurity的检测

public class CodeFilter extends HttpFilter {@Overrideprotected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {String uri = req.getServletPath();if (uri.equals("/login") && req.getMethod().equalsIgnoreCase("post")) {// 服务端生成的验证码数据String sessionCode = req.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY).toString();System.out.println("正确的验证码: " + sessionCode);// 用户输入的验证码数据String formCode = req.getParameter("code").trim();System.out.println("用户输入的验证码: " + formCode);if (StringUtils.isEmpty(formCode)) {throw new RuntimeException("验证码不能为空");}if (sessionCode.equals(formCode)) {System.out.println("验证通过");} else {throw new AuthenticationServiceException("验证码输入不正确");}}chain.doFilter(req, res);}}

 数据库

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/security?serverTimezone=GMT%2B8driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: rootmain:allow-circular-references: true #开始支持spring循环依赖

当第一次执行项目时,会在库中生成表数据 


http://www.ppmy.cn/news/1330939.html

相关文章

HTML标签(二)

目录 表格标签 表格的主要作用 表格的具体用法 表头单元格标签 表格属性 表格结构标签 合并单元格 合并单元格的方式&#xff1a; 跨行合并&#xff1a; 跨列合并&#xff1a; 列表标签 无序列表 有序列表 自定义列表 表单标签 表单域 表单域的常用属性 表单元素…

架构师成长之路 - 项目架构、领域模型经验总结(持续更新,自留笔记)

目录 前言 一、项目分层设计 二、领域模型对象 三、项目顶层架构设计和调用链

[Android] Android文件系统中存储的内容有哪些?

文章目录 前言root 文件系统/system 分区稳定性:安全性: /system/bin用来提供服务的二进制可执行文件:调试工具:UNIX 命令&#xff1a;调用 Dalvik 的脚本(upall script):/system/bin中封装的app_process脚本 厂商定制的二进制可执行文件: /system/xbin/system/lib[64]/system/…

从零学Java MySQL

MySQL 文章目录 MySQL初识数据库思考&#xff1a;1 什么是数据库&#xff1f;2 数据库管理系统 初识MySQLMySQL卸载MySQL安装1 配置环境变量2 MySQL目录结构及配置文件 连接MySQL数据库基本命令MySQL基本语法&#xff1a;1 查看MySQL服务器中所有数据库2 创建数据库3 查看数据库…

三、Nacos源码系列:Nacos服务注册流程(二) - NotifyCenter事件发布机制

目录 一、NotifyCenter类分析 1.1、NotifyCenter简介 1.2、DefaultPublisher 1.3、DefaultSharePublisher 二、事件发布 三、事件处理 四、总结 一、NotifyCenter类分析 通过对Nacos服务端处理客户端的服务注册请求的分析&#xff0c;我们看到好像并没有处理很多事情。…

【教程】如何在苹果手机上查看系统文件?

​ 目录 引言 用户登录工具和连接设备 查看设备信息&#xff0c;电池信息 查看硬盘信息 硬件信息 查看 基带信息 销售信息 电脑可对手机应用程序批量操作 运行APP和查看APP日志 IPA包安装测试 注意事项 引言 苹果手机与安卓手机不同&#xff0c;无法直接访问系统文件…

ASCB1系列一体式智能微型断路器 智慧空开-安科瑞 蒋静

1. 概述 ASCB1系列智能微型断路器(一体式)&#xff08;以下简称智能微型断路器&#xff09;应用于户内建筑物及类似场所的工业、商业、民用建筑及基础设施等领域低压终端配电网络。智能微型断路器对用电线路的关键电气参数&#xff0c;如电压、电流、功率、温度、漏电、能耗等…

数据结构之树和森林

数据结构之树和森林 1、树的存储结构2、树和森林的遍历2.1、树的遍历2.2、森林的遍历 3、树、森林和二叉树之间的相互转换 数据结构是程序设计的重要基础&#xff0c;它所讨论的内容和技术对从事软件项目的开发有重要作用。学习数据结构要达到的目标是学会从问题出发&#xff0…