package com.shi.shiro; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import org.springframework.http.HttpRequest; /** * 自定义的验证码校验过滤器 继承FormAuthenticationFilter * @author SHF * 问题: 之后全部的都要进行验证码校验 (这个要解决) * */ public class CustomFormAuthenticationFilter extends FormAuthenticationFilter{ //覆盖FormAuthenticationFilter 认证的方法 @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { //1 先进行验证码的校验 //从session中获取正确的验证码 HttpServletRequest httpRequest=(HttpServletRequest)request; /*HttpSession session=httpRequest.getSession(); //从session中取出正确的 验证码信息 String validateCode=(String) session.getAttribute("validateCode");*/ //模拟从session中取出正确的验证码 String validateCode="abc"; //取出页面输入的验证码 String realmCode=httpRequest.getParameter("realmCode"); System.out.println("页面输入的验证码是:"+realmCode); if(validateCode!=null && realmCode!=null && !validateCode.equals(realmCode)){ //2 验证码认证失败 讲验证码错误信息保存到request中的 shiroLoginFailure 属性中 httpRequest.setAttribute("shiroLoginFailure", "realmErr"); //拒绝访问 ,不在验证帐号和密码 return true; } //3 验证码认证成功 就进行用户名和密码的认证 return super.onAccessDenied(request, response); } }
2 配置自定义CustomFormAuthenticationFilterjava
<!-- 7.1 自定义form认证过滤器 --> <bean id="formAuthenticationFilter" class="com.shi.shiro.CustomFormAuthenticationFilter"> <!-- 表单帐号中 input名称 --> <property name="usernameParam" value="username"></property> <!-- 表单中密码的input名称 --> <property name="passwordParam" value="password"></property> </bean> <!-- 1 配置filter对应的bean --> <!-- shiro的web过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 1.1 配置安全管理器 --> <property name="securityManager" ref="securityManager"/> <!-- 1.2 loginUrl认证提交地址,若是没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证--> <property name="loginUrl" value="/login.action" /> <!-- 1.3 unauthorizedUrl指定没有权限时跳转页面--> <property name="unauthorizedUrl" value="/refuse.action" /> <!-- 1.5 配置成功页面 --> <property name="successUrl" value="/first.action"/> <!-- 7.2 把自定义的filter配置到 过滤器链中 --> <property name="filters"> <map> <!-- 讲自定义的CustomFormAuthenticationFilter 注入到shiroFilter中 --> <entry key="authc" value-ref="formAuthenticationFilter"></entry> </map> </property> <!-- 1.4 过滤器链的定义 --> <property name="filterChainDefinitions"> <value> <!-- 对静态资源进行匿名访问 --> /images/**=anon <!-- 请求logout.action地址,shiro去清空session --> /logout.action=logout <!-- /**=authc 表示全部url都必须认证经过以后开能够访问 --> <!-- 受权的控制 下面经过注解的方式开启受权--> <!-- /items/query.action=perms[items:query] /user/query.action=perms[user:query] --> <!-- 对全部剩下的认证 --> /**=authc <!-- /**=anon anon全部的url均可以匿名访问 --> <!-- /**=anon --> </value> </property> </bean>
3 在login.action对验证错误 进行解析web
//登陆提交地址,和applicationContext-shiro.xml文件 中配置的loginUrl保持一致 @RequestMapping("/login") public String Login(HttpServletRequest request) throws Exception{ //若是失败从request中获取认证异常信息,shiroLoginFilure就是shiro异常类的权限类名 /*String exceptionClassName=request.getParameter("shiroLoginFailure");*/ String exceptionClassName=(String) request.getAttribute("shiroLoginFailure"); System.out.println("登陆异常=========="+exceptionClassName); //根据shiro返回的异常类路径判断,抛出指定异常信息 if(exceptionClassName!=null){ if(UnknownAccountException.class.getName().equals(exceptionClassName)){ throw new CustomException("帐户不存在"); }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){ System.out.println("密码错误"); throw new CustomException("用户名/密码错误"); }else if("realmErr".equals(exceptionClassName)){ throw new CustomException("验证码错误"); }else{ throw new Exception();//最终在异常处理器生成未知异常 } }
4 在登录页面添加验证码spring
5 在filter配置匿名访问验证码jspapache