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

来源:互联网 发布:淘宝阿里云手机登录 编辑:程序博客网 时间:2024/05/18 01:53

一、前言

前面通过注解和缓存做了权限验证,这里增加验证码与记住登录功能。注意:shiro缓存是权限授权的缓存。

二、验证码

2.1编写继承FormAuthenticationFilter的权限验证自定义类

重写一个验证验证码的onAccessDenied方法

CustomFormAuthenticationFilter.java
package com.ycy.shiro;import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;/** * Created by Administrator on 2015/10/20 0020. */public class CustomFormAuthenticationFilter extends FormAuthenticationFilter  {    @Override    protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {        // 校验验证码        // 从session获取正确的验证码        HttpSession session = ((HttpServletRequest)request).getSession();        //页面输入的验证码        String randomcode = request.getParameter("randomcode");        //从session中取出验证码        String validateCode = (String) session.getAttribute("validateCode");        if (randomcode!=null&&validateCode!=null&&!randomcode.equals(validateCode)) {            // randomCodeError表示验证码错误            request.setAttribute("shiroLoginFailure", "randomCodeError");            //拒绝访问,不再校验账号和密码            return true;        }        return super.onAccessDenied(request, response, mappedValue);    }}

2.2 登录获取我们自定义验证

package com.ycy.controller;import com.ycy.Exception.CustomException;import com.ycy.model.ActiveUser;import com.ycy.service.SysService;import org.apache.shiro.authc.IncorrectCredentialsException;import org.apache.shiro.authc.UnknownAccountException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;/** *  * <p>Title: LoginController</p> * <p>Description: 登陆和退出</p> */@Controllerpublic class LoginController {@Autowiredprivate SysService sysService;//用户登陆提交方法@RequestMapping("/login")public  String login(HttpServletRequest request)throws Exception{//如果登录失败从request中获取认证异常信息,shrioLoginFailure就是shiro异常类的全限定名String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");//根据shrio返回的异常路径判断,抛出指定异常信息if (exceptionClassName!=null){if(UnknownAccountException.class.getName().equals(exceptionClassName)){//抛出异常throw new CustomException("账户不存在");}else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){throw new CustomException("用户名/密码错误");}else if("randomCodeError".equals(exceptionClassName)){throw new CustomException("验证码错误");} else {throw new Exception("未知错误");}}return "login";}}

2.3 注入自定义的FormAuthenticationFilter

在applicationContext中注入我们自己定义的验证器

<beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"       xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">    <!-- Shiro 的Web过滤器 -->    <!--================================================1、与web.xml对应的bean===================================-->    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager" />        <!-- 如果没有认证将要跳转的登陆地址,http可访问的url,如果不在表单认证过虑器FormAuthenticationFilter中指定此地址就为身份认证地址 -->        <property name="loginUrl" value="/login" />        <!-- 没有权限跳转的地址 -->        <property name="unauthorizedUrl" value="/pages/jsp/refuse.jsp" />        <!-- 自定义filter配置 -->        <property name="filters">            <map>                <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中-->                <entry key="authc" value-ref="formAuthenticationFilter" />            </map>        </property>        <!--过滤定义,从上而下,蒋匿名的anon放最下面-->        <property name="filterChainDefinitions">            <value>                <!--静态资源通过-->                /js/** anon                /images/** anon                /styles/** anon                <!-- 验证码,可匿名访问 -->                /pages/jsp/validatecode.jsp = anon                <!--商品查询需要商品查询权限(权限表达式)尽量有注解-->                <!--/items/queryItems=perms[item:query]-->                <!--表示所有请求url必须通过认证-->                /**=  authc                <!--请求logout,shrio擦除sssion-->                /logout=logout                <!--表示所有url都可以通过-->               <!-- /**  anon-->            </value>        </property>    </bean>    <!-- ==============================================2、安全管理器============================================== -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="realm" ref="userRealm" />        <!--缓存管理-->        <property name="sessionManager" ref="sessionManager" />        <property name="cacheManager" ref="cacheManager"/>    </bean>    <!-- 缓存管理器 -->    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">        <property name="cacheManagerConfigFile" value="classpath:cache/ehcache.xml"/>    </bean>    <!-- 会话管理器 -->    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">        <!-- session的失效时长,单位毫秒 -->        <property name="globalSessionTimeout" value="600000"/>        <!-- 删除失效的session -->        <property name="deleteInvalidSessions" value="true"/>    </bean>    <!-- 自定义form认证过虑器 -->    <!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 -->    <bean id="formAuthenticationFilter" class="com.ycy.shiro.CustomFormAuthenticationFilter">        <!--表单中账户和密码的input框名称-->        <property name="usernameParam" value="username"/>        <property name="passwordParam" value="password"/>    </bean>    <!--==============================================3、realm===================================================-->    <!-- Shiro配置,继承自AuthorizingRealm的自定义Realm (解决初始化时的依赖循环问题,通过这里向realm中注入userservice实现)-->    <bean id="userRealm" class="com.ycy.shiro.CustomRealm" >        <property name="authorizationCacheName" value="authorizationcache" />        <property name="credentialsMatcher" ref="credentialsMatcher" />    </bean>    <!--4 凭证匹配器 -->    <bean id="credentialsMatcher"          class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">        <property name="hashAlgorithmName" value="md5" />        <property name="hashIterations" value="1" />    </bean></beans>

2.4 在页面编写验证码

<TR><TD>验证码:</TD><TD><input id="randomcode" name="randomcode" size="8" /> <img id="randomcode_img"  alt=""width="56" height="20" align='absMiddle' src="${baseurl}pages/jsp/validatecode.jsp"  onclick="randomcode_refresh()"/> <ahref=javascript:randomcode_refresh()>刷新</a></TD></TR>


2.5 设置验证码能够匿名访问

      <value>                <!--静态资源通过-->                /js/** anon                /images/** anon                /styles/** anon                <!-- 验证码,可匿名访问 -->                /pages/jsp/validatecode.jsp = anon                <!--请求logout,shrio擦除sssion-->                /logout=logout                <!--商品查询需要商品查询权限(权限表达式)尽量有注解-->                <!--/items/queryItems=perms[item:query]-->                <!--表示所有请求url必须通过认证-->                /**=  authc                <!--表示所有url都可以通过-->               <!-- /**  anon-->            </value>        </property>
验证码页面图片:



三、记住登录设置

就是写入cookie,shrio本身就支持。

1、用户序列号

public class SysPermission implements Serializable{    private Long id;    private String name;    private String type;    private String url;    private String percode;    private Long parentid;


2、记住登录xml配置

<beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"       xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.0.xsd ">    <!-- Shiro 的Web过滤器 -->    <!--================================================1、与web.xml对应的bean===================================-->    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager" />        <!-- 如果没有认证将要跳转的登陆地址,http可访问的url,如果不在表单认证过虑器FormAuthenticationFilter中指定此地址就为身份认证地址 -->        <property name="loginUrl" value="/login" />        <!-- 没有权限跳转的地址 -->        <property name="unauthorizedUrl" value="/pages/jsp/refuse.jsp" />        <!-- 自定义filter配置 -->        <property name="filters">            <map>                <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中-->                <entry key="authc" value-ref="formAuthenticationFilter" />            </map>        </property>        <!--过滤定义,从上而下,蒋匿名的anon放最下面-->        <property name="filterChainDefinitions">            <value>                <!--静态资源通过-->                /js/** anon                /images/** anon                /styles/** anon                <!-- 验证码,可匿名访问 -->                /pages/jsp/validatecode.jsp = anon                <!--请求logout,shrio擦除sssion-->                /logout=logout                <!--商品查询需要商品查询权限(权限表达式)尽量有注解-->                <!--/items/queryItems=perms[item:query]-->                <!-- 配置记住我或认证通过可以访问的地址 -->                /index.jsp  = user                /first = user                /welcome.jsp = user                <!--表示所有请求url必须通过认证-->                /**=  authc                <!--表示所有url都可以通过-->               <!-- /**  anon-->            </value>        </property>    </bean>    <!-- ==============================================2、安全管理器============================================== -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="realm" ref="userRealm" />        <!--缓存管理-->        <property name="sessionManager" ref="sessionManager" />        <property name="cacheManager" ref="cacheManager"/>        <!-- 记住我 -->        <property name="rememberMeManager" ref="rememberMeManager"/>    </bean>    <!-- 缓存管理器 -->    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">        <property name="cacheManagerConfigFile" value="classpath:cache/ehcache.xml"/>    </bean>    <!-- 会话管理器 -->    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">        <!-- session的失效时长,单位毫秒 -->        <property name="globalSessionTimeout" value="600000"/>        <!-- 删除失效的session -->        <property name="deleteInvalidSessions" value="true"/>    </bean>    <!-- 自定义form认证过虑器 -->    <!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 -->    <bean id="formAuthenticationFilter" class="com.ycy.shiro.CustomFormAuthenticationFilter">        <!--表单中账户和密码的input框名称-->        <property name="usernameParam" value="username"/>        <property name="passwordParam" value="password"/>        <property name="rememberMeParam" value="rememberMe"/>    </bean>    <!--==============================================3、realm===================================================-->    <!-- Shiro配置,继承自AuthorizingRealm的自定义Realm (解决初始化时的依赖循环问题,通过这里向realm中注入userservice实现)-->    <bean id="userRealm" class="com.ycy.shiro.CustomRealm" >        <property name="authorizationCacheName" value="authorizationcache" />        <property name="credentialsMatcher" ref="credentialsMatcher" />    </bean>    <!--4 凭证匹配器 -->    <bean id="credentialsMatcher"          class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">        <property name="hashAlgorithmName" value="md5" />        <property name="hashIterations" value="1" />    </bean>    <!--==============================================rememberMeManager管理器========================================-->    <!-- rememberMeManager管理器 -->    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">        <property name="cookie" ref="rememberMeCookie" />    </bean>    <!-- 记住我cookie -->    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">        <constructor-arg value="rememberMe" />        <!-- 记住我cookie生效时间30天 -->        <property name="maxAge" value="2592000" />    </bean></beans>
1其中记住登录为

<!--==============================================rememberMeManager管理器========================================-->    <!-- rememberMeManager管理器 -->    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">        <property name="cookie" ref="rememberMeCookie" />    </bean>    <!-- 记住我cookie -->    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">        <constructor-arg value="rememberMe" />        <!-- 记住我cookie生效时间30天 -->        <property name="maxAge" value="2592000" />    </bean>
2需要加入securityManager
 <!-- 记住我 -->        <property name="rememberMeManager" ref="rememberMeManager"/>

3获取记住我的input属性
    <bean id="formAuthenticationFilter" class="com.ycy.shiro.CustomFormAuthenticationFilter">        <!--表单中账户和密码的input框名称-->        <property name="usernameParam" value="username"/>        <property name="passwordParam" value="password"/>        <!--记住我input框名称-->        <property name="rememberMeParam" value="rememberMe"/>    </bean>



3、登录页面设置

<TR><TD></TD><TD><input type="checkbox" name="rememberMe" />自动登陆</TD></TR>


4、测试记住登录

查询cookie是否有我们的记录,而且可以查询cookie用户页面,用到另一个过滤器 user。在securityManager配置过滤器

    <!-- 配置记住我或认证通过可以访问的地址 -->                /index.jsp  = user                /first = user                /welcome.jsp = user

如图:可以访问欢迎页面,不能访问商品管理页面。

总结记住登录:设置记住登录管理器====注入securityManager=======设置input=============设置选择框name属性==========设置user拦截器访问页面

user拦截器“

user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

0 0
原创粉丝点击