spring security 中验证码的实现,当验证码不正确的时候,页面会跳转至500错误页面。 20

但是我的需求是跳转到login页面,并提示验证码错误的信息。该如何实现... 但是我的需求是跳转到login页面,并提示验证码错误的信息。该如何实现 展开
 我来答
WZYEclipse疏疏
2016-05-29 · TA获得超过421个赞
知道小有建树答主
回答量:333
采纳率:0%
帮助的人:275万
展开全部
有三中方法可以实现验证码的功能
第一种是自定义一个filter,放在SpringSecurity过滤器之前,在用户登录的时候会先经过这个filter,然后在这个filter中实现对验证码进行验证的功能,这种方法不推荐,因为它已经脱离了SpringSecurity
第二种是自定义一个filter让它继承自UsernamePasswordAuthenticationFilter,然后重写attemptAuthentication方法在这个方法中实现验证码的功能,如果验证码错误就抛出一个继承自AuthenticationException的验证吗错误的异常比如(CaptchaException),然后这个异常就会被SpringSecurity捕获到并将异常信息返回到前台,这种实现起来比较简单

[java] view plain copy
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {

String requestCaptcha = request.getParameter(this.getCaptchaFieldName());
String genCaptcha = (String)request.getSession().getAttribute("code");

logger.info("开始校验验证码,生成的验证码为:"+genCaptcha+" ,输入的验证码为:"+requestCaptcha);

if( !genCaptcha.equals(requestCaptcha)){
throw new CaptchaException(
this.messageSource.getMessage("AbstractUserDetailsAuthenticationProvider.badCaptcha",null,"Default",null));
}
return super.attemptAuthentication(request, response);
}
然后在配置文件中配置下

[html] view plain copy
<bean id="loginFilter" class="com.zrhis.system.security.DefaultUsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="authenticationSuccessHandler">
<bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/index.jsp"></property>
</bean>
</property>
<property name="authenticationFailureHandler">
<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp"></property>
</bean>
</property>
</bean>
最后在http中加入custom-filter配置,将这个filter放在SpringSecurity的FORM_LOGIN_FILTER之前

[html] view plain copy
<custom-filter ref="loginFilter" before="FORM_LOGIN_FILTER"/>
最后一种是直接替换掉SpringSecurity的UsernamePasswordAuthenticationFilter,这种比较复杂,但是更为合理,也是我现在正在用的。

如果用这种方法那么http 中的auto-config就必须去掉,而form-login配置也必须去掉,因为这个不需要了,里面的属性都需要我们自行注入。
首先需要创建一个EntryPoint

[html] view plain copy
<bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp" />
</bean>
然后在http中配置下

[html] view plain copy
<sec:http access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationEntryPoint">
然后我们来写CaptchaAuthenticationFilter,同样需要继承自UsernamePasswordAuthenticationFilter

[java] view plain copy
public class CaptchaAuthenticationFilter extends UsernamePasswordAuthenticationFilter{

public static final String SPRING_SECURITY_FORM_CAPTCHA_KEY = "j_captcha";
public static final String SESSION_GENERATED_CAPTCHA_KEY = Constant.SESSION_GENERATED_CAPTCHA_KEY;

private String captchaParameter = SPRING_SECURITY_FORM_CAPTCHA_KEY;

public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {

String genCode = this.obtainGeneratedCaptcha(request);
String inputCode = this.obtainCaptcha(request);
if(genCode == null)
throw new CaptchaException(this.messages.getMessage("LoginAuthentication.captchaInvalid"));
if(!genCode.equalsIgnoreCase(inputCode)){
throw new CaptchaException(this.messages.getMessage("LoginAuthentication.captchaNotEquals"));
}

return super.attemptAuthentication(request, response);
}

protected String obtainCaptcha(HttpServletRequest request){
return request.getParameter(this.captchaParameter);
}

protected String obtainGeneratedCaptcha (HttpServletRequest request){
return (String)request.getSession().getAttribute(SESSION_GENERATED_CAPTCHA_KEY);
}

}
在配置文件中配置CaptchaAuthenticationFilter

[html] view plain copy
<bean id="captchaAuthenticaionFilter" class="com.zrhis.system.security.CaptchaAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<property name="filterProcessesUrl" value="/login.do" />
</bean>

<bean id="authenticationSuccessHandler" class="com.zrhis.system.security.SimpleLoginSuccessHandler">
<property name="defaultTargetUrl" value="/WEB-INF/app.jsp"></property>
<property name="forwardToDestination" value="true"></property>
</bean>
<bean id="authenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp" />
</bean>
从配置文件中就可以看出来authenticationManager、authenticationFailureHandler、authenticationSuccessHandler、filterProcessesUrl等都需要我们自行注入了。

filterProcessesUrl定义的是登录验证的地址,默认的是j_spring_security_check这里我们改成login.do
authenticationSuccessHandler中的defaultTargetUrl定义的是登录成功后跳转到的页面
authenticationFailureHandler中的defaultTargetUrl定义的是登录失败后跳转到的页面
我们的首页app.jsp在/WEB-INF下所以需要使用服务器跳转,所以需要将forwardToDestination设为true,因为客户端跳转是不能直接访问WEB-INF下的内容的。
最后在http中将FORM_LOGIN_FILTER替换掉,最终http中完整的配置就变成了下面的内容

[html] view plain copy
<sec:http access-decision-manager-ref="accessDecisionManager"
entry-point-ref="authenticationEntryPoint">

<sec:access-denied-handler ref="accessDeniedHandler"/>

<sec:session-management invalid-session-url="/login.jsp" />

<sec:custom-filter ref="filterSecurityInterceptor" before="FILTER_SECURITY_INTERCEPTOR"/>
<sec:custom-filter ref="captchaAuthenticaionFilter" position="FORM_LOGIN_FILTER"/>
</sec:http>

custom-filter中before是在这个filter之前,after是之后,position是替换。
追问
我使用的是第三种方式,但是我在验证码错误的时候,抛出new CaptchaException(this.messages.getMessage("LoginAuthentication.captchaNotEquals")一异常的时候,无法将这个对象new出来,我不知道我是包错了还是什么情况,很郁闷。然后验证码错误的时候,他就会直接跳转到500页面。
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式