700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Spring Boot 整合 Shiro(三)Kaptcha验证码 附源码

Spring Boot 整合 Shiro(三)Kaptcha验证码 附源码

时间:2022-05-19 01:06:03

相关推荐

Spring Boot 整合 Shiro(三)Kaptcha验证码 附源码

前言

本文是根据上篇《Spring Boot 整合Shiro(二)加密登录与密码加盐处理》进行修改,如有不明白的转上篇文章了解。

1.导入依赖

<!-- /artifact/com.github.penggle/kaptcha --><dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version></dependency>

2.配置

创建KaptchaConfig.java

import com.google.code.kaptcha.impl.DefaultKaptcha;import com.google.code.kaptcha.util.Config;import org.springframework.context.annotation.Bean;import org.ponent;import java.util.Properties;@Componentpublic class KaptchaConfig {@Beanpublic DefaultKaptcha getDefaultKaptcha() {com.google.code.kaptcha.impl.DefaultKaptcha defaultKaptcha = new com.google.code.kaptcha.impl.DefaultKaptcha();Properties properties = new Properties();// 图片边框properties.setProperty("kaptcha.border", "yes");// 边框颜色properties.setProperty("kaptcha.border.color", "105,179,90");// 字体颜色properties.setProperty("kaptcha.textproducer.font.color", "red");// 图片宽properties.setProperty("kaptcha.image.width", "110");// 图片高properties.setProperty("kaptcha.image.height", "40");// 字体大小properties.setProperty("kaptcha.textproducer.font.size", "30");// session keyproperties.setProperty("kaptcha.session.key", "code");// 验证码长度properties.setProperty("kaptcha.textproducer.char.length", "4");// 字体properties.setProperty("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");//可以设置很多属性,具体看com.google.code.kaptcha.Constants//kaptcha.border 是否有边框 默认为true 我们可以自己设置yes,no//kaptcha.border.color 边框颜色 默认为Color.BLACK//kaptcha.border.thickness 边框粗细度 默认为1//kaptcha.producer.impl 验证码生成器 默认为DefaultKaptcha//kaptcha.textproducer.impl 验证码文本生成器 默认为DefaultTextCreator//kaptcha.textproducer.char.string 验证码文本字符内容范围 默认为abcde2345678gfynmnpwx//kaptcha.textproducer.char.length 验证码文本字符长度 默认为5//kaptcha.textproducer.font.names 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)//kaptcha.textproducer.font.size 验证码文本字符大小 默认为40//kaptcha.textproducer.font.color 验证码文本字符颜色 默认为Color.BLACK//kaptcha.textproducer.char.space 验证码文本字符间距 默认为2//kaptcha.noise.impl 验证码噪点生成对象 默认为DefaultNoise//kaptcha.noise.color 验证码噪点颜色 默认为Color.BLACK//kaptcha.obscurificator.impl 验证码样式引擎 默认为WaterRipple//kaptcha.word.impl 验证码文本字符渲染 默认为DefaultWordRenderer//kaptcha.background.impl 验证码背景生成器 默认为DefaultBackground//kaptcha.background.clear.from 验证码背景颜色渐进 默认为Color.LIGHT_GRAY//kaptcha.background.clear.to 验证码背景颜色渐进 默认为Color.WHITE//kaptcha.image.width 验证码图片宽度 默认为200//kaptcha.image.height 验证码图片高度 默认为50Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}}

3.验证码生成/验证

import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;import javax.imageio.ImageIO;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import com.google.code.kaptcha.impl.DefaultKaptcha;@Controller@RequestMapping(value ="/kaptcha" )public class KaptchaController {/*** 1、验证码工具*/@AutowiredDefaultKaptcha defaultKaptcha;/*** 2、生成验证码* @param httpServletRequest* @param httpServletResponse* @throws Exception*/@RequestMapping("/defaultKaptcha")public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)throws Exception {byte[] captchaChallengeAsJpeg = null;ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();try {// 生产验证码字符串并保存到session中String createText = defaultKaptcha.createText();httpServletRequest.getSession().setAttribute("rightCode", createText);// 使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中BufferedImage challenge = defaultKaptcha.createImage(createText);ImageIO.write(challenge, "jpg", jpegOutputStream);} catch (IllegalArgumentException e) {httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);return;}// 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组captchaChallengeAsJpeg = jpegOutputStream.toByteArray();httpServletResponse.setHeader("Cache-Control", "no-store");httpServletResponse.setHeader("Pragma", "no-cache");httpServletResponse.setDateHeader("Expires", 0);httpServletResponse.setContentType("image/jpeg");ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();responseOutputStream.write(captchaChallengeAsJpeg);responseOutputStream.flush();responseOutputStream.close();}/*** 3、校对验证码* @param httpServletRequest* @param httpServletResponse* @return*/@RequestMapping("/imgvrifyControllerDefaultKaptcha")public ModelAndView imgvrifyControllerDefaultKaptcha(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) {ModelAndView andView = new ModelAndView();String rightCode = (String) httpServletRequest.getSession().getAttribute("rightCode");String tryCode = httpServletRequest.getParameter("tryCode");System.out.println("rightCode:"+rightCode+" ———— tryCode:"+tryCode);if (!rightCode.equals(tryCode)) {andView.addObject("info", "错误的验证码");andView.setViewName("/login");} else {andView.addObject("info", "登录成功");andView.setViewName("success");}return andView;}}

4.修改ShiroConfig

开放相应的验证码路径,避免拦截

@Bean(name = "shiroFilter")public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();// Shiro的核心安全接口,这个属性是必须的shiroFilterFactoryBean.setSecurityManager(securityManager);// 身份认证失败,则跳转到登录页面的配置shiroFilterFactoryBean.setLoginUrl("/login");// 权限认证失败,则跳转到指定页面shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();// <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->filterChainDefinitionMap.put("/webjars/**", "anon");filterChainDefinitionMap.put("/login", "anon");filterChainDefinitionMap.put("/loginOut", "anon");filterChainDefinitionMap.put("/", "anon");filterChainDefinitionMap.put("/front/**", "anon");filterChainDefinitionMap.put("/api/**", "anon");filterChainDefinitionMap.put("/kaptcha/**", "anon");filterChainDefinitionMap.put("/success/**", "anon");filterChainDefinitionMap.put("/admin/**", "authc");filterChainDefinitionMap.put("/user/**", "authc");//主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证filterChainDefinitionMap.put("/**", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}

5.修改LoginController

@Controller@RequestMappingpublic class LoginController {private Logger logger = Logger.getLogger(this.getClass().getName());/*** 界面* @return*/@RequestMapping(value = "/login", method = RequestMethod.GET)public String defaultLogin() {return "login";}/*** 退出* @return*/@RequestMapping(value = "/loginOut", method = RequestMethod.GET)public String loginOut() {Subject subject = SecurityUtils.getSubject();subject.logout();return "login";}/*** 登录提交* @param username* @param tryCode* @param password* @param redirectAttributes* @return*/@RequestMapping(value = "/login", method = RequestMethod.POST)public String login(@RequestParam("username") String username,@RequestParam("tryCode") String tryCode,@RequestParam("password") String password,RedirectAttributes redirectAttributes) {//判断验证码if(StringUtils.isBlank(tryCode)){logger.info("验证码为空了!");redirectAttributes.addFlashAttribute("message", "验证码不能为空!");return "redirect:login";}Session session = SecurityUtils.getSubject().getSession();String code = (String) session.getAttribute("rightCode");System.out.println(code+"*************"+tryCode);if(!tryCode.equalsIgnoreCase(code)){logger.info("验证码错误!");redirectAttributes.addFlashAttribute("message", "验证码错误!");return "redirect:login";}// 从SecurityUtils里边创建一个 subjectSubject subject = SecurityUtils.getSubject();// 在认证提交前准备 token(令牌)UsernamePasswordToken token = new UsernamePasswordToken(username, password);String attributeValue = null;// 执行认证登陆try {subject.login(token);} catch (UnknownAccountException uae) {attributeValue="未知账户!";} catch (IncorrectCredentialsException ice) {attributeValue="密码不正确!";} catch (LockedAccountException lae) {attributeValue= "账户已锁定";} catch (ExcessiveAttemptsException eae) {attributeValue= "用户名或密码错误次数过多";} catch (AuthenticationException ae) {attributeValue= "用户名或密码不正确!";}finally {redirectAttributes.addFlashAttribute("message", attributeValue);if (subject.isAuthenticated()) {return "success";} else {token.clear();return "redirect:login";}}}}

6.界面

6.1整合thymeleaf模板

添加依赖;

<!--thymeleaf--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>

编辑application.yml

server:port: 80servlet:context-path: /#thymeleaf模板spring:thymeleaf:cache: trueprefix:classpath: /templates/suffix: .htmlmode: HTML5encoding: UTF-8servlet:content-type: text/html

6.2创建

login.html

<!DOCTYPE html><!-- thymeleaf 提示功能 --><html xmlns:th="" xmlns="/1999/html"><head lang="en"><meta charset="UTF-8"></meta><title>验证码</title></head><style type="text/css">body {padding: 10px}</style><body><!-- 提示 --><h3 th:text="${message}"></h3><div><!-- 后面添加参数起到清除缓存作用 --><img alt="验证码" onclick="this.src='/kaptcha/defaultKaptcha?d='+new Date()*1" src="/kaptcha/defaultKaptcha" /></div><form action="/login" method="post">账户:<input type="text" name="username" /></br>密码:<input type="text" name="password" /></br>验证码:<input type="text" name="tryCode" /><input type="submit" value="提交" ></input></form></body></html>

success.html

<!DOCTYPE html><html><head><meta charset="UTF-8"></meta><title>成功</title></head><body><h1>登录成功</h1><a href="/loginOut">退出</a></body></html>

7. 实战演练

8.项目源码

《源码下载》

下篇介绍Spring Boot 整合 Shiro(四)thymeleaf模板权限控制 附源码

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。