springboot + shiro 验证码与记住登录

标签: shiro spring-boot
13人阅读 评论(0) 收藏 举报
分类:

验证码实现

关于kaptcha

kaptcha 是一个很有用的验证码生成工具。有了它,你能够生成各种样式的验证码,由于它是可配置的。使用kaptcha能够方便的配置:
* 验证码的字体
* 验证码字体的大小
* 验证码字体的字体颜色
* 验证码内容的范围(数字,字母,中文汉字!)
* 验证码图片的大小。边框,边框粗细,边框颜色
* 验证码的干扰线(能够自己继承com.google.code.kaptcha.NoiseProducer写一个自己定义的干扰线)
* 验证码的样式(鱼眼样式、3D、普通模糊……当然也能够继承com.google.code.kaptcha.GimpyEngine自己定义样式)

maven依赖

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

注入验证码Servlet

KaptchaConfig.java

@Component
public class KaptchaConfig {
    @Bean
    public ServletRegistrationBean<KaptchaServlet> kaptchaServlet() {

        ServletRegistrationBean<KaptchaServlet> registrationBean = new ServletRegistrationBean<>(new KaptchaServlet(), "/captcha/kaptcha.jpg");

        registrationBean.addInitParameter(Constants.KAPTCHA_SESSION_CONFIG_KEY,
                Constants.KAPTCHA_SESSION_KEY);
        //宽度
        registrationBean.addInitParameter(Constants.KAPTCHA_IMAGE_WIDTH,"140");
        //高度
        registrationBean.addInitParameter(Constants.KAPTCHA_IMAGE_HEIGHT,"60");
        //字体大小
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE,"50");
//        registrationBean.addInitParameter(Constants.KAPTCHA_BORDER_THICKNESS,"1"); //边框
        //无边框
        registrationBean.addInitParameter(Constants.KAPTCHA_BORDER,"no");
        //文字颜色
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        //长度
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
        //字符间距
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "6");

        //可以设置很多属性,具体看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
        return registrationBean;
    }
}

在这里我们注入了一个链接为“/captcha/kaptcha.jpg”的servlet。点击运行项目打开链接如果看到验证码图片,则说明配置成功了。

验证码拦截器

CaptchaValidateFilter.java

ublic class CaptchaValidateFilter extends AccessControlFilter {
    private String captchaParam = "captchaCode"; //前台提交的验证码参数名  

    private String failureKeyAttribute = "shiroLoginFailure";  //验证失败后存储到的属性名  

    public String getCaptchaCode(ServletRequest request) {
        return WebUtils.getCleanParam(request, getCaptchaParam());
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
            throws Exception {
        // 从session获取正确的验证码
        Session session = SecurityUtils.getSubject().getSession();
        //页面输入的验证码
        String captchaCode = getCaptchaCode(request);
        String validateCode = (String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY);

        HttpServletRequest httpServletRequest = WebUtils.toHttp(request);  
        //判断验证码是否表单提交(允许访问)  
        if ( !"post".equalsIgnoreCase(httpServletRequest.getMethod())) {  
            return true;  
        } 

        // 若验证码为空或匹配失败则返回false
        if(captchaCode == null) {
            return false;
        } else if (validateCode != null) {
            captchaCode = captchaCode.toLowerCase();
            validateCode = validateCode.toLowerCase();
            if(!captchaCode.equals(validateCode)) {
                return false;
            }
        }
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
         //如果验证码失败了,存储失败key属性  
        request.setAttribute(failureKeyAttribute, "验证码错误");  
        return true;  
    }

    public String getCaptchaParam() {
        return captchaParam;
    }

    public void setCaptchaParam(String captchaParam) {
        this.captchaParam = captchaParam;
    }
}

验证码拦截器继承了AccessControlFilter,该类提供了访问控制的基础功能,比如是否允许访问/当访问拒绝时如何处理等。主要有两个方法:
* isAccessAllowed:表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
* onAccessDenied:表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可

修改ShiroConfig.java

public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不会被拦截的链接 顺序判断

        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/layui/**", "anon");
        filterChainDefinitionMap.put("/captcha/**", "anon");
        filterChainDefinitionMap.put("/favicon.ico", "anon");

        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");
        //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问; user”表示访问该地址的用户是身份验证通过或RememberMe登录的都可以-->
        filterChainDefinitionMap.put("/add", "perms[add]");
        filterChainDefinitionMap.put("/login", "captchaVaildate,authc");

        filterChainDefinitionMap.put("/**", "user");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");

        //自定义拦截器
        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        filters.put("captchaVaildate", new CaptchaValidateFilter());
        filters.put("authc", new MyFormAuthenticationFilter());
        return shiroFilterFactoryBean;
    }

在表单验证拦截器前加入验证码拦截器

记住登录实现

ShiroConfig的配置

在ShiroConfig.java中添加如下方法:

    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ......
        shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setSecurityManager(securityManager);
        .....
}
  /**
     * 安全管理器
     * @return securityManager
     */
    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());

        //注入记住我管理器
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    /**
     * cookie对象;
     * rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cookie的有效时间等等。
     * @return rememberMeCookie
     */
    @Bean
    public SimpleCookie rememberMeCookie(){
        //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
        SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
        //<!-- 记住我cookie生效时间30天 ,单位秒;-->
        simpleCookie.setMaxAge(30*24*60*60);
        simpleCookie.setHttpOnly(true);
        return simpleCookie;
    }

    /**
     * cookie管理对象;
     * rememberMeManager()方法是生成rememberMe管理器,而且要将这个rememberMe管理器设置到securityManager中
     * @return rememberMeManager
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){
        CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
        cookieRememberMeManager.setCookie(rememberMeCookie());
        //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
        cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
        return cookieRememberMeManager;
    }

......

login页面

<!DOCTYPE html>
<html  lang="en" class="no-js" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8"/>
    <title>登录--layui后台管理模板</title>
    <link rel="stylesheet" href="../../layui/css/layui.css" media="all" />

    <link rel="stylesheet" href="../css/login.css" media="all" />
</head>
<body>
<div class="login">
    <h1>layuiCMS-管理登录</h1>
    <form class="layui-form" method="post">
        <div class="layui-form-item">
            <input class="layui-input" name="username" placeholder="用户名" type="text" autocomplete="off"/>
        </div>
        <div class="layui-form-item">
            <input class="layui-input" name="password" placeholder="密码"  type="password" autocomplete="off"/>
        </div>
        <div class="layui-form-item form_code">
            <input class="layui-input"  name="captchaCode" placeholder="验证码" lay-verify="required" type="text" autocomplete="off"/>
            <div>
                <img type="image" src="../captcha/kaptcha.jpg" id="codeImage" onclick="chageCode()" title="图片看不清?点击重新得到验证码" style="cursor:pointer;" width="116" height="36"/>
            </div>
        </div>
        <div class="layui-form-item">
            <input type="checkbox" name="rememberMe" title="记住我" lay-skin="primary"/>
        </div>

        <button class="layui-btn login_btn" lay-submit="" lay-filter="login">登录</button>
    </form>
</div>
<script type="text/javascript" src="../layui/layui.js"></script>

<script th:inline="javascript">

layui.use(['layer'], function(){
    var layer = layui.layer;
    var message = [[${shiroLoginFailure}]]?[[${shiroLoginFailure}]]:getUrlPara("shiroLoginFailure");
    if(message) {
        layer.msg(message);
    }           
});

function getUrlPara(name)
{
    var url = document.location.toString();
    var arrUrl = url.split("?"+name +"=");
    var para = arrUrl[1];
    console.log(para);
    if(para)
        return decodeURI(para);
}
function chageCode(){
    document.getElementById("codeImage").src="../captcha/kaptcha.jpg?"+Math.random();
}

</script>
</body>
</html>
查看评论

SpringBoot+Shiro学习之“记住我”和“GIF验证码”功能的实现

如题
  • qq_20954959
  • qq_20954959
  • 2017-02-26 18:13:57
  • 497

shrio教程初级(八)shiro验证码与记住登录

一、前言 前面通过注解和缓存做了权限验证,这里增加验证码与记住登录功能。 二、验证码 2.1编写继承FormAuthenticationFilter的权限验证自定义类 重写一个验证验证码的onAcce...
  • yangchangyong0
  • yangchangyong0
  • 2015-10-20 15:44:07
  • 7137

SpringBoot学习:整合shiro(rememberMe记住我功能)

项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 首先在shiro配置类中注入rememberMe管理器 /** * cookie对象...
  • aqsunkai
  • aqsunkai
  • 2017-04-08 22:34:49
  • 2353

SpringBoot学习:整合shiro(验证码功能和登录次数限制功能)

(一)验证码 首先login.jsp里增加了获取验证码图片的标签: 登录页面---- /login" method="post"> 用户名 : ...
  • aqsunkai
  • aqsunkai
  • 2017-04-08 23:08:54
  • 1603

SpringBoot + shiro Demo 简单登录验证权限验证

  • 2018年02月08日 17:02
  • 86KB
  • 下载

spring boot 集成shiro记住我实现

1). Shiro简单介绍 对shiro不了解的可以前往http://www.vxzsk.com/560.html学习 Shiro是Apache下的一个开源项目,我们称之为Apache Shiro...
  • u012100371
  • u012100371
  • 2017-09-07 09:08:45
  • 464

SpringBoot使用Shiro验证登录笔记

笔记: 1.使用Authentication,验证用户登录 1、Authentication:是验证用户身份的过程。 2、Authorization:是授权访问控制,用于对用户进行的...
  • Damionew
  • Damionew
  • 2017-12-06 10:00:31
  • 422

Spring Boot +Shiro 验证码Filter和限制密码错误次数

验证码校验CustomFormAuthenticationFilter 将我们自己实现的Filter,放到ShiroFilterFactoryBean中。 ShiroFilterFactoryBean...
  • LJY_SUPER
  • LJY_SUPER
  • 2017-09-05 16:54:48
  • 347

spring-shiro外篇记住我功能

it浪子号 2017-04-09 18:57 记住我功能在各大网站是比较常见的,实现起来也是大同小异,主要就是利用cookie来实现,而shiro对记住我功能的实现也是比较简单的,只需要几步...
  • u011277123
  • u011277123
  • 2017-04-17 18:32:42
  • 3436

SpringBoot+Shiro学习之密码加密和登录失败次数限制

springboot+shiro学习笔记
  • qq_20954959
  • qq_20954959
  • 2017-03-13 20:49:12
  • 682
    个人资料
    等级:
    访问量: 1421
    积分: 90
    排名: 156万+
    文章分类
    最新评论