使用shiro的的表单过滤器重写shiro默认的认证规则来实现先验证验证码再验证登录所遇到的问题

来源:互联网 发布:赚淘宝运费险犯法吗 编辑:程序博客网 时间:2024/05/18 00:34

我之前写过一篇用shiro实现登录认证的博文,今天就是在这基础上做出修改而成。由于对shiro认识不够深入,折腾了很久,今天主要就是对遇到的问题做出点小总结。

首先我先给出shiro的配置文件:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">    <!--web.xml中shiro的filter对应的bean-->    <!-- Shiro 的Web过滤器 -->    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager"/>        <!--loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证-->        <property name="loginUrl" value="/login"/>        <property name="successUrl" value="/homepage"/>        <!--自定义的filter-->        <property name="filters">            <map>                <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中 -->                <entry key="authc" value-ref="formAuthenticationFilter"/>            </map>        </property>        <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->        <property name="filterChainDefinitions">            <value>                <!--对静态资源设置匿名访问-->                /images/**=anon                /js/**=anon                /style/**=anon                /resources/**=anon                /kaptcha**=anon                /homepage=anon                <!-- -/**=authc 表示所有的url都必须认证通过才可以访问- -->                /**=authc            </value>        </property>    </bean>    <!--securityManage-->    <!-- 安全管理器 -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="realm" ref="customRealm"/>        <!--注入会话管理器-->        <property name="sessionManager" ref="sessionManager"/>    </bean>    <!--自定义realm-->    <bean id="customRealm" class="shiro.shirorealm.CustomRealm">        <!--将凭证匹配器设置到我们自定义realm的配置中-->        <property name="credentialsMatcher" ref="credentialsMatcher"/>    </bean>    <!--数据库中存储到的md5的散列值,在realm中需要设置数据库中的散列值它使用散列算法及散列次数,  让shiro进行散列对比时和原始数据库中的散列值使用的算法一致-->    <!-- (密码)凭证匹配器 -->    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">        <property name="hashAlgorithmName" value="md5" />    </bean>    <!--会话管理器-->    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">        <property name="sessionIdUrlRewritingEnabled" value="false" />        <!-- session的失效时长,单位毫秒 -->        <property name="globalSessionTimeout" value="600000"/>        <!-- 删除失效的session -->        <property name="deleteInvalidSessions" value="true"/>    </bean>    <!--自定义的from认证过滤器-->    <bean id="formAuthenticationFilter" class="filter.CustomFromAuthenticationFilter">        <!-- 表单中账号的input名称 -->        <property name="usernameParam" value="username"/>        <!-- 表单中密码的input名称 -->        <property name="passwordParam" value="password"/>    </bean></beans>

在这要注意的是,过滤器链,而我遇到的问题也正是过滤器链所导致的。

问题一:我集成了kaptcha来实现验证码,但是发现最后到页面的时候,发现当我点击换一张的时候就不能显示了。

原因:原因是因为我在过滤器链那设置验证码是可匿名访问,但是生成验证码也有个controller,所以有个url。最初我是这样设置的:“/kaptcha=anon”,这就造成了当我点击换一张的时候,找不到路径所以不显示。这还有个原因是在我设置了更新验证码的方法那。为了不让验证码缓存,所以在每次更新的时候都会在/kaptcha路径后面加个时间:/kaptcha?=new Date().getTime();这就导致路径发生了变化。

解决方法:将/kaptcha=anon改成/kaptcha**=anon,让它匹配以“/kaptcha”开头的验证码链接。



问题二:当我验证成功后想跳转到成功页面,但是报404错误,老是跳转到xxx.ico

疑惑:我在shiro的配置文件中已经加入了成功后跳转的设置l<property name="successUrl" value="/homepage"/> ,但就是不行。

原因:原因是successUrl的配置只是作为一种附加的配置,只有session中没有用户请求地址的时候才会使用successUrl。

解决方法:由于我是使用restful风格来拦截,所以这时应该复写FormAuthenticationFilter的onLoginSuccess()方法。代码如下:

 @Override    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {        WebUtils.issueRedirect(request,response,getSuccessUrl());        return false;    }


重点:重写shiro的表单过滤器来加入验证码验证的逻辑。关于自定义filter的配置,上面的shiro的配置文件都写上了

public class CustomFromAuthenticationFilter extends FormAuthenticationFilter{    @Override    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {        HttpServletRequest httpServletRequest= (HttpServletRequest) request;        HttpSession session=httpServletRequest.getSession();        String verifyCode;        try{            verifyCode=httpServletRequest.getParameter("verifyCode").toUpperCase();        }catch (NullPointerException e){            verifyCode=null;        }        //判断验证码输入是否正确        if(verifyCode!=null && !verifyCode.equals(session.getAttribute(Constants.KAPTCHA_SESSION_KEY))){            //如果校验失败,将验证码错误的失败信息,通过shiroLoginFailure设置到request中            httpServletRequest.setAttribute("shiroLoginFailure","randomCodeError");            //拒绝访问,不再校验账号和密码            return true;        }        return super.onAccessDenied(request, response);    }    @Override    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {        WebUtils.issueRedirect(request,response,getSuccessUrl());        return false;    }}


1 0
原创粉丝点击