文档章节

springboot+shiro实现验证码

zheng875
 zheng875
发布于 2017/01/24 17:42
字数 781
阅读 319
收藏 3

shiro使用FormAuthenticationFilter进行表单认证,验证校验的功能应该加在FormAuthenticationFilter中,在认证之前进行验证码校验。

需要写FormAuthenticationFilter的子类,继承FormAuthenticationFilter,改写它的认证方法,在认证之前进行验证码校验。

1.自定义FormAuthenticationFilter

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter{  
    @Override    
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {    
        // 在这里进行验证码的校验    
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;    
        HttpSession session = httpServletRequest.getSession();    
    
        // 取出验证码    
        String validateCode = (String) session.getAttribute("validateCode");    
        // 取出页面的验证码    
        // 输入的验证和session中的验证进行对比    
        String randomcode = httpServletRequest.getParameter("randomcode");    
        if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) {    
            // 如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中    
            httpServletRequest.setAttribute("shiroLoginFailure", "kaptchaValidateFailed");//自定义登录异常    
            // 拒绝访问,不再校验账号和密码    
            return true;    
        }    
        return super.onAccessDenied(request, response);    
    }    
}  

2.在ShiroConfiguration.java中的shiroFilter方法注入自定义FormAuthenticationFilter

添加定义的过滤器,并且将生成验证码的servlet设定为可匿名访问。

3.登录方法加入自定义的异常kaptchaValidateFailed

 @RequestMapping(value="/login",method=RequestMethod.POST)
    public String login(HttpServletRequest request, Map<String, Object> map){
        System.out.println("HomeController.login()");
        // FormAuthenticationFilter定义了出错异常,自定义的异常,也可以继承此类下添加
        String exception = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
        System.out.println("exception=" + exception);

        String msg = "";
        if (exception != null) {
            if (UnknownAccountException.class.getName().equals(exception)) {
                System.out.println("UnknownAccountException -- > 账号不存在:");
                msg = "UnknownAccountException -- > 账号不存在:";
            } else if (IncorrectCredentialsException.class.getName().equals(exception)) {
                System.out.println("IncorrectCredentialsException -- > 密码不正确:");
                msg = "IncorrectCredentialsException -- > 密码不正确:";
            } else if ("kaptchaValidateFailed".equals(exception)) {
                System.out.println("kaptchaValidateFailed -- > 验证码错误");
                msg = "kaptchaValidateFailed -- > 验证码错误";
            } else if (ExcessiveAttemptsException.class.getName().equals(exception)) {
                System.out.println("ExcessiveAttemptsException -- > 登录失败次数过多:");
                msg = "ExcessiveAttemptsException -- > 登录失败次数过多:";
            }else if ("kaptchaValidateFailed".equals(exception)) {
                System.out.println("kaptchaValidateFailed -- > 验证码错误");
                msg = "kaptchaValidateFailed -- > 验证码错误";
            }
            else {
                msg = "else >> "+exception;
                System.out.println("else -- >" + exception);
            }
        }
        map.put("msg", msg);
        // 此方法不处理登录成功,由shiro进行处理.
        return "login";
    }

4.修改login.html

<!DOCTYPE html>    
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"  
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">  
<head>    
<meta charset="UTF-8" />    
<title>Insert title here</title>    
</head>    
<body>    
            错误信息:<h4 th:text="${msg}"></h4>    
       <form action="" method="post">    
           <p>账号:<input type="text" name="username" value="admin"/></p>    
           <p>密码:<input type="text" name="password" value="123456"/></p>    
           <p>验证码:<input type="text" name="randomcode"/>  
           <img th:src="@{/validatecodeServlet}" height="20px" width="60px" onclick="random(this)"/></p>   
           <P><input type="checkbox" name="rememberMe" />记住我</P>   
           <p><input type="submit" value="登录"/></p>    
       </form>    
       <script th:inline="javascript">  
          function random(tmp){  
               tmp.src="/validatecodeServlet?rnd="+Math.random();  
          }  
       </script>  
</body>    
</html>  

5.生成验证码servlet

@WebServlet(urlPatterns="/validatecodeServlet")  
public class ValidatecodeServlet extends HttpServlet{  
     /**  
     *   
     */  
    private static final long serialVersionUID = 1L;  
  
    @Override    
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {    
            System.out.println(">>>>>>>>>>doGet()<<<<<<<<<<<");    
            doPost(req, resp);    
        }    
        
        @Override    
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {    
            System.out.println(">>>>>>>>>>doPost()<<<<<<<<<<<");    
            int width = 60;  
            int height = 32;  
            //create the image  
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
            Graphics g = image.getGraphics();  
            // set the background color  
            g.setColor(new Color(0xDCDCDC));  
            g.fillRect(0, 0, width, height);  
            // draw the border  
            g.setColor(Color.black);  
            g.drawRect(0, 0, width - 1, height - 1);  
            // create a random instance to generate the codes  
            Random rdm = new Random();  
            String hash1 = Integer.toHexString(rdm.nextInt());  
            System.out.print(hash1);  
            // make some confusion  
            for (int i = 0; i < 50; i++) {  
                int x = rdm.nextInt(width);  
                int y = rdm.nextInt(height);  
                g.drawOval(x, y, 0, 0);  
            }  
            // generate a random code  
            String capstr = hash1.substring(0, 4);  
            HttpSession session = req.getSession(true);  
            //将生成的验证码存入session  
            session.setAttribute("validateCode", capstr);  
            g.setColor(new Color(0, 100, 0));  
            g.setFont(new Font("Candara", Font.BOLD, 24));  
            g.drawString(capstr, 8, 24);  
            g.dispose();  
            //输出图片  
            resp.setContentType("image/jpeg");  
            OutputStream strm = resp.getOutputStream();  
            ImageIO.write(image, "jpeg", strm);  
            strm.close();     
             
        }    
}  

 

6.Application.java添加注解

@ServletComponentScan

7.效果

8.代码

https://git.oschina.net/zheng875/springboottemplate

持续集成中。。。。。。。。。。。。。。。。。。。

© 著作权归作者所有

zheng875
粉丝 11
博文 47
码字总数 22528
作品 0
无锡
程序员
私信 提问
springboot+shiro

springboot添加shiro依赖后jar包冲突?怎么搞啊

樱木花道VS康
2018/06/28
312
3
shiro拦截器使用的问题(springboot+shiro)

使用shiro开发的时候,配置拦截器有什么作用吗?配置了拦截器之后因该怎么写才能处理拦截到的请求呢? 初始化的时候配置了拦截器。但是是跳到了controller之后调用的Subject.login()方法进入...

HaleyZhang
2018/08/31
1K
2
shiro使用疑问

大家好我用springboot+shiro搭建项目,shiro自定义了sessiondao继承了 使用redis缓存session信息,在配置 的时候配置 还有一个属性: setSessionDAO是添加自定义的session使用redis缓村sessi...

樱木花道VS康
2018/07/03
44
1
使用 JCaptcha 开发图形和声音验证码

当前越来越多的网站系统采用 CAPTCHA 验证码,来阻止垃圾信息发布机器人的信息提交,但通常绝大多数网站,只提供图片验证码,而这将影响盲人用户的使用。JCaptcha 是一个 Java 开源项目,利用...

IBMdW
2012/02/29
2.8K
2
php如何实现验证码

验证码在表单实现越来越多了,但是用js的写的验证码,总觉得不方便,所以学习了下php实现的验证码。 验证码在表单实现越来越多了,但是用js的写的验证码,总觉得不方便,所以学习了下php实现...

snowing1990
2016/04/15
44
0

没有更多内容

加载失败,请刷新页面

加载更多

JS基础-该如何理解原型、原型链?

JS的原型、原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对这个...

OBKoro1
今天
7
0
高防CDN的出现是为了解决网站的哪些问题?

高防CDN是为了更好的服务网络而出现的,是通过高防DNS来实现的。高防CDN是通过智能化的系统判断来路,再反馈给用户,可以减轻用户使用过程的复杂程度。通过智能DNS解析,能让网站访问者连接到...

云漫网络Ruan
今天
14
0
OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
3K
24
SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
46
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部