代码语言:javascript复制
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 配置自定义CustomFormAuthenticationFilter
代码语言:javascript复制<!-- 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对验证错误 进行解析
代码语言:javascript复制//登录提交地址,和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 在登陆页面添加验证码
5 在filter配置匿名访问验证码jsp