自定义了一个表单fileter以及一个realm。登陆请求能被fileter拦截,但是总是不进入realm.
fileter:
public class CustomFromAuthenticationFilter extends FormAuthenticationFilter
{
@Override
protected boolean onAccessDenied(ServletRequest request,ServletResponse response) throws Exception {
System.out.println("1");
//在这里进行验证码的校验
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; }
return super.onAccessDenied(request, response);
}
}spring-shiro.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.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="/testController/login.do"/>
<!--认证成功统一跳转到first.actio,建议不配置,不配置的话shiro认证成功会自动到上一个请求路径-->
<!-- <property name="successUrl" value="/testController/success.do"/> -->
<property name="unauthorizedUrl" value="/refuse.html" /> <!--自定义filter-->
<property name="filters">
<map>
<!-- 将自定义的FormAuthenticationFilter注入shiroFiler中 -->
<entry key="authc" value-ref="formAuthenticationFilter" />
</map>
</property> <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->
<property name="filterChainDefinitions">
<value>
<!--设置静态资源可以直接访问-->
/view/css/**=anon
/view/imgs/**=anon
/view/js/**=anon
/view/html/login.html=anon
<!--请求这个地址就自动退出-->
/testController/logout.do=logout
<!--商品查询需要商品查询权限,取消url拦截配置,采用注解授权-->
<!--/items/queryItems.action=perms[item:query]-->
<!--<!–商品修改需要商品修改权限–>-->
<!--/items/editItems.action=perms[item:edit]--> <!--配置记住我或认证通过可以访问的地址--> <!-- -/**=authc 表示所有的url都必须认证通过才可以访问- -->
/**= authc
<!--/**=anon 表示所有的url都可以匿名访问--> </value>
</property>
</bean> <!--securityManage-->
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="customRealm" /> <!--注入缓存管理器-->
<!-- <property name="cacheManager" ref="cacheManager"/> --> <!--注入会话管理器-->
<!-- <property name="sessionManager" ref="sessionManager" /> --> <!-- 记住我 -->
<!-- <property name="rememberMeManager" ref="rememberMeManager"/> -->
</bean> <!--自定义realm-->
<bean id="customRealm" class="com.web.ssm.shiro.CustomRealm">
<!--将凭证匹配器设置到realm中,realm按照凭证匹配器要求进行散列-->
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean> <!-- 凭证匹配器 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5" />
<property name="hashIterations" value="1" />
</bean> <!-- 缓存管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
</bean>
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- session的失效时长,单位毫秒 -->
<property name="globalSessionTimeout" value="600000"/>
<!-- 删除失效的session -->
<property name="deleteInvalidSessions" value="true"/>
</bean>
<!--自定义form认证过滤器-->
<bean id="formAuthenticationFilter" class="com.web.ssm.shiro.CustomFromAuthenticationFilter">
<!-- 表单中账号的input名称 -->
<property name="usernameParam" value="username" />
<!-- 表单中密码的input名称 -->
<property name="passwordParam" value="password" />
<!--记住我input的名称-->
<!-- <property name="rememberMeParam" value="rememberMe"/> -->
</bean> <!-- rememberMeManager管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cookie" ref="rememberMeCookie" />
</bean>
<!-- 记住我cookie -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!--rememberMe时cookie的名字-->
<constructor-arg value="rememberMe" />
<!-- 记住我cookie生效时间30天 -->
<property name="maxAge" value="2592000" />
</bean>
</beans>
自定义realm:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
//token是用户输入的
//第一步:丛token中取出身份信息
String userCode= (String) token.getPrincipal();
String pass=MD5Util.md5Pwd("123456");
System.out.println("2");
SimpleAuthenticationInfo simpleAuthenticationInfo=new
SimpleAuthenticationInfo(userCode,pass,this.getName());
return simpleAuthenticationInfo;
}
controller:
@RequestMapping(value="/login")
public String login(HttpServletRequest request,HttpServletResponse response, Model model) throws Exception{
//如果登录失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名
String exceptionClassName= (String) request.getAttribute("shiroLoginFailure");
System.out.println("3");
//根据shiro返回的异常类路径判断,抛出指定异常信息
if(exceptionClassName!=null){
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
//最终会抛给异常处理器
request.setAttribute("error", "账号不存在");
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
request.setAttribute("error", "用户名/密码错误");
} else if("randomCodeError".equals(exceptionClassName)){
request.setAttribute("error", "用户名/密码错误");
} else{
throw new Exception();//最终在异常处理器生成未知错误
}
} //此方法不处理登录成功,shiro认证成功会自动跳转到上一个路径 //登录失败返回到login页面
return "login";
}login.html:
<body>
<div class="main">
<h1 class="lean">Login</h1>
<form class="form-horizontal" role="form" id="default-form" action="testController/login.do" method="post">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">
<span class="glyphicon glyphicon-user"></span>
</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="username" id="username" placeholder="Username">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">
<span class="glyphicon glyphicon-lock"></span>
</label>
<div class="col-sm-9">
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
<span class="help-block" th:text="${error}">dfasffadsfas</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-9">
<div class="checkbox">
<label>
<input type="checkbox">Remember
</label>
<label style="display: inline-block;float:right;">Go register</label>
</div>
</div>
</div>
<button type="submit" class="log-btn btn-danger btn-radius"><span class="glyphicon glyphicon-chevron-right"></span></button>
</form>
</div>
</body>
fileter:
public class CustomFromAuthenticationFilter extends FormAuthenticationFilter
{
@Override
protected boolean onAccessDenied(ServletRequest request,ServletResponse response) throws Exception {
System.out.println("1");
//在这里进行验证码的校验
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; }
return super.onAccessDenied(request, response);
}
}spring-shiro.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
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/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.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="/testController/login.do"/>
<!--认证成功统一跳转到first.actio,建议不配置,不配置的话shiro认证成功会自动到上一个请求路径-->
<!-- <property name="successUrl" value="/testController/success.do"/> -->
<property name="unauthorizedUrl" value="/refuse.html" /> <!--自定义filter-->
<property name="filters">
<map>
<!-- 将自定义的FormAuthenticationFilter注入shiroFiler中 -->
<entry key="authc" value-ref="formAuthenticationFilter" />
</map>
</property> <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->
<property name="filterChainDefinitions">
<value>
<!--设置静态资源可以直接访问-->
/view/css/**=anon
/view/imgs/**=anon
/view/js/**=anon
/view/html/login.html=anon
<!--请求这个地址就自动退出-->
/testController/logout.do=logout
<!--商品查询需要商品查询权限,取消url拦截配置,采用注解授权-->
<!--/items/queryItems.action=perms[item:query]-->
<!--<!–商品修改需要商品修改权限–>-->
<!--/items/editItems.action=perms[item:edit]--> <!--配置记住我或认证通过可以访问的地址--> <!-- -/**=authc 表示所有的url都必须认证通过才可以访问- -->
/**= authc
<!--/**=anon 表示所有的url都可以匿名访问--> </value>
</property>
</bean> <!--securityManage-->
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="customRealm" /> <!--注入缓存管理器-->
<!-- <property name="cacheManager" ref="cacheManager"/> --> <!--注入会话管理器-->
<!-- <property name="sessionManager" ref="sessionManager" /> --> <!-- 记住我 -->
<!-- <property name="rememberMeManager" ref="rememberMeManager"/> -->
</bean> <!--自定义realm-->
<bean id="customRealm" class="com.web.ssm.shiro.CustomRealm">
<!--将凭证匹配器设置到realm中,realm按照凭证匹配器要求进行散列-->
<property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean> <!-- 凭证匹配器 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5" />
<property name="hashIterations" value="1" />
</bean> <!-- 缓存管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
</bean>
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
<!-- session的失效时长,单位毫秒 -->
<property name="globalSessionTimeout" value="600000"/>
<!-- 删除失效的session -->
<property name="deleteInvalidSessions" value="true"/>
</bean>
<!--自定义form认证过滤器-->
<bean id="formAuthenticationFilter" class="com.web.ssm.shiro.CustomFromAuthenticationFilter">
<!-- 表单中账号的input名称 -->
<property name="usernameParam" value="username" />
<!-- 表单中密码的input名称 -->
<property name="passwordParam" value="password" />
<!--记住我input的名称-->
<!-- <property name="rememberMeParam" value="rememberMe"/> -->
</bean> <!-- rememberMeManager管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<property name="cookie" ref="rememberMeCookie" />
</bean>
<!-- 记住我cookie -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!--rememberMe时cookie的名字-->
<constructor-arg value="rememberMe" />
<!-- 记住我cookie生效时间30天 -->
<property name="maxAge" value="2592000" />
</bean>
</beans>
自定义realm:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
//token是用户输入的
//第一步:丛token中取出身份信息
String userCode= (String) token.getPrincipal();
String pass=MD5Util.md5Pwd("123456");
System.out.println("2");
SimpleAuthenticationInfo simpleAuthenticationInfo=new
SimpleAuthenticationInfo(userCode,pass,this.getName());
return simpleAuthenticationInfo;
}
controller:
@RequestMapping(value="/login")
public String login(HttpServletRequest request,HttpServletResponse response, Model model) throws Exception{
//如果登录失败从request中获取认证异常信息,shiroLoginFailure就是shiro异常类的全限定名
String exceptionClassName= (String) request.getAttribute("shiroLoginFailure");
System.out.println("3");
//根据shiro返回的异常类路径判断,抛出指定异常信息
if(exceptionClassName!=null){
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
//最终会抛给异常处理器
request.setAttribute("error", "账号不存在");
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
request.setAttribute("error", "用户名/密码错误");
} else if("randomCodeError".equals(exceptionClassName)){
request.setAttribute("error", "用户名/密码错误");
} else{
throw new Exception();//最终在异常处理器生成未知错误
}
} //此方法不处理登录成功,shiro认证成功会自动跳转到上一个路径 //登录失败返回到login页面
return "login";
}login.html:
<body>
<div class="main">
<h1 class="lean">Login</h1>
<form class="form-horizontal" role="form" id="default-form" action="testController/login.do" method="post">
<div class="form-group">
<label for="username" class="col-sm-2 control-label">
<span class="glyphicon glyphicon-user"></span>
</label>
<div class="col-sm-9">
<input type="text" class="form-control" name="username" id="username" placeholder="Username">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">
<span class="glyphicon glyphicon-lock"></span>
</label>
<div class="col-sm-9">
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
<span class="help-block" th:text="${error}">dfasffadsfas</span>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-9">
<div class="checkbox">
<label>
<input type="checkbox">Remember
</label>
<label style="display: inline-block;float:right;">Go register</label>
</div>
</div>
</div>
<button type="submit" class="log-btn btn-danger btn-radius"><span class="glyphicon glyphicon-chevron-right"></span></button>
</form>
</div>
</body>
Controller的login方法
应该有这么一句:
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPwd());
token.setRememberMe(user.isRemenber());
SecurityUtils.getSubject().login(token);