首页
友链
关于
免责声明
Search
1
王者营地战绩数据王者荣耀查询网页源码
6,210 阅读
2
群晖Active Backup for Business套件备份Linux服务器教程
4,384 阅读
3
影视分享
4,313 阅读
4
(亲测)Jrebel激活破解方式2019-08-21
4,289 阅读
5
centos7 安装及卸载 jekenis
3,573 阅读
日常
文章
后端
前端
Linux
异常
Flutter
分享
群辉
登录
Search
标签搜索
docker
springboot
Spring Boot
java
linux
Shiro
Graphics2D
图片
游戏账号交易
Mybatis
Spring Cloud
centos
脚本
Web Station
群辉
王者营地
战绩查询
平台对接
Spring Cloud Alibaba
nacos
绿林寻猫
累计撰写
249
篇文章
累计收到
26
条评论
首页
栏目
日常
文章
后端
前端
Linux
异常
Flutter
分享
群辉
页面
友链
关于
免责声明
搜索到
1
篇与
Kaptcha
的结果
2021-12-08
Spring Boot 整合 Shiro(三)Kaptcha验证码 附源码
前言本文是根据上篇《Spring Boot 整合Shiro(二)加密登录与密码加盐处理》进行修改,如有不明白的转上篇文章了解。1.导入依赖 <!-- https://mvnrepository.com/artifact/com.github.penggle/kaptcha --> <dependency> <groupId>com.github.penggle</groupId> <artifactId>kaptcha</artifactId> <version>2.3.2</version> </dependency> 2.配置创建KaptchaConfig.javaimport com.google.code.kaptcha.impl.DefaultKaptcha; import com.google.code.kaptcha.util.Config; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import java.util.Properties; @Component public class KaptchaConfig { @Bean public 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 key properties.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 验证码图片高度 默认为50 Config 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、验证码工具 */ @Autowired DefaultKaptcha 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 @RequestMapping public 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里边创建一个 subject Subject 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.ymlserver: port: 80 servlet: context-path: / #thymeleaf模板 spring: thymeleaf: cache: true prefix: classpath: /templates/ suffix: .html mode: HTML5 encoding: UTF-8 servlet: content-type: text/html 6.2创建login.html<!DOCTYPE html> <!-- thymeleaf 提示功能 --> <html xmlns:th="http://www.thymeleaf.org" xmlns="http://www.w3.org/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模板权限控制 附源码
2021年12月08日
388 阅读
0 评论
0 点赞