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

我之前写过一篇用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
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值