shiro- session,自定义FormAuthenticationFilter(表单认证器)-->实现验证码校验


需求:实现验证码功能



shiro使用FormAuthenticationFilter进行表单认证,验证校验的功能应该写在FormAuthenticationFilter中

在认证(验证账号和密码)之前进行验证码校验。


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



1.sessionManager

和shiro整合后,使用shiro的session管理,shiro提供sessionDao操作 会话数据


配置sessionManager

<!-- securityManager -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	<!-- 将realm注入到当前的securityManager中 -->
	<property name="realm" ref="customRealm"></property>
	<!-- 注入缓存管理器 -->
	<property name="cacheManager" ref="cacheManager"></property>
	<!-- 注入session管理器 -->
	<property name="sessionManager" ref="sessionManager"></property>
</bean>

<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
	<!-- session的失效时长,单位为毫秒 -->
	<property name="globalSessionTimeout" value="600000"></property>
	<!-- 删除失效的session -->
	<property name="deleteInvalidSessions" value="true"></property>
</bean>




2.自定义FormAuthenticationFilter


//自定义的表达认证器要继承FormAuthenticationFilter
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter{

	//原FormAuthenticationFilter的认证方法
	protected boolean onAccessDenied(ServletRequest request,
			ServletResponse response) throws Exception {
		//在这里进行验证码校验
		
		//在session获取正确验证码
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		HttpSession session = httpServletRequest.getSession();
		//在session中取出正确的验证码
		String validateCode = (String)session.getAttribute("validateCode");
		
		//取出用户输入的验证码
		String randomcode = httpServletRequest.getParameter("randomcode");
		//进行校验
		if(randomcode!=null && validateCode!=null && !randomcode.equals(validateCode)){
			//如果校验失败,将验证码错误失败的信息,通过shiroLoginFailure设置到request
			httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");
			//拒绝访问
			return true;
		}			
		
		//验证码正确,调用父类的onAccessDenied方法进行username和password的校验
		return super.onAccessDenied(request, response);
	}
}



3.配置自定义的FormAuthenticationFilter


在shiro的过滤器中配置,applicationContext-shiro.xml


<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 配置安全管理器 -->
<property name="securityManager" ref="securityManager"></property>	
<!-- 
	如果账户还没有认证就进行请求,当请求访问的资源不是匿名的话,
	就会将其请求拦截到下面这个url中 ,进行登录认证
-->
<property name="loginUrl" value="/login.action"></property>
<!-- 这是认证之后访问没有权限的资源,会统一跳转到这个jsp -->
<property name="unauthorizedUrl" value="/refuse.jsp"></property>

<!-- 自定义filter配置 -->
<property name="filters">
	<map>	
		<!-- 将自定义的FormAuthenticationFilter注入shiroFilter中 -->
		<entry key="authc" value-ref="formAuthenticationFilter"></entry>
	</map>
</property>

<!-- 配置自定义form认证过滤器 -->
<bean id="formAuthenticationFilter" class="cn.itcast.ssm.shiro.CustomFormAuthenticationFilter">
	<!-- 表单中账号的input名称 -->
	<property name="usernameParam" value="username"></property>
	<!-- 表单中密码的input名称 -->
	<property name="passwordParam" value="password"></property>
</bean>


4.在login.action对验证错误 进行解析

	@RequestMapping("login")
	public String login(HttpServletRequest request) throws Exception{
		
		/**
		 * 如果登录失败从request中获取认证的异常信息,
		 * shiroLoginFailure就是shiro异常类的全限类名,
		 * 可以获取异常信息,其实抛出异常信息就是抛出异常信息的类名
		 */
		String exceptionClassName = request.getParameter("shiroLoginFailure");
		
		//根据shiro返回的异常类路径判断,抛出指定的异常信息
		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();//最终在异常处理器生成未知错误
			}
		}
		
		/**
		 * 	这个方法-login(),这个方法是处理认证不成功的
		 * 认证是交给shiro处理的,在applicationContext-shiro.xml中配置拦截器
		 * 当请求的url为:login.action的时候,它首先是不会进入这个方法,而是被shiro的拦截器给拦住了,
		 * 		进入了shiro的认证机制,shiro最终会调用自定义的realm进行认证,
		 * 		通过用户输入的与数据库的比对,如果不正常的话,这时候才会进入到这个方法,其中抛出的异常信息
		 * 		可以在request中获取,通过request.getParameter("shiroLoginFailure")可以获取
		 * 
		 * shiro认证成功会自动跳转到上一个请求的路径
		 * 	登录失败跳转到login页面
		 * 
		 */
		return "login";
	}



5.在登陆页面添加验证码

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


6.在filter配置匿名访问验证码jsp

<!-- 验证码,可匿名访问 -->
/validatecode.jsp = anon





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值