SpringSecurity 踩坑了,遇到了无限循环认证的问题。具体是认证失败后,我想转发到登录页面,并且返回一些提示信息,结果就踩坑了。
我是 SpringMVC 4.1.7,SpringSecurity 4.0.4
这是 xml 配置
<security:form-login login-page="/admin/login"
login-processing-url="/admin/login"
username-parameter="username"
password-parameter="password" />
我配置了登录页面是 /admin/login
,登录表单提交的地址是 /admin/login
当认证失败时,SpringSecurity 默认的失败处理器是 SimpleUrlAuthenticationFailureHandler
类,它默认采用重定向的方式,重定向到 login-page
设置的 URL,也就是重定向到登录页面。
然后我想在认证失败后,根据失败信息返回给客户端一些友好的提示。但是采用重定向的方式,我的提示信息就丢失了,客户端无法收到提示信息。所以我想将重定向的方式改成转发的方式。
这是我改后的 xml 配置
<security:form-login login-page="/admin/login"
login-processing-url="/admin/login"
username-parameter="username"
password-parameter="password"
authentication-failure-handler-ref="simpleUrlAuthenticationFailureHandler"/>
<bean id="simpleUrlAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<constructor-arg name="defaultFailureUrl" value="/admin/login"></constructor-arg>
<property name="useForward" value="true" />
</bean>
我手动配置了 SimpleUrlAuthenticationFailureHandler
类,将 useForward
属性设置为 true
,表示启用转发的方式。defaultFailureUrl
属性设置为 /admin/login
,表示转发到登录页面。这里说明一下,defaultFailureUrl
属性是认证失败后,重定向或者转发的 URL。如果不设置,默认是 login-page
的值。
重启后发现果然采用了转发的方式,但是这样又遇到了一个问题,转发到 /admin/login
之后,又进入了认证的方法,认证失败后又转发到 /admin/login
,然后又进入认证的方法,一直无限循环下去。。。
仔细想了一下,应该是我的配置出了问题
我配置的登录页是 /admin/login
,请求方法是 GET
,登录表单提交的地址是 /admin/login
,请求方式是 POST
,也就是说登录页面和登录提交的地址都是同一个
,唯一的区别是请求方法不同。
转发之前的地址是 admin/login
,请求方法是 POST
,由于转发是同一个请求,它的请求方法不会变,所以转发的请求方法也是 POST
。又由于我设置的转发 URL 是admin/login
,所以转发之后又会进入认证的方法,相当于重新提交了登录表单。所以无论如何都不会进入到登录页面,所以就会造成无限循环。
这里也特别说明一下,为什么默认的重定向不会造成无限循环。因为重定向是客户端的行为,相当于客户端重新发起请求,并且重定向肯定是 GET
请求,所以会正常进入到登录页面,不会造成无线循环。
最后的 xml 配置如下:
<security:form-login login-page="/admin/login.jsp"
login-processing-url="/admin/login"
username-parameter="username"
password-parameter="password"
authentication-failure-handler-ref="simpleUrlAuthenticationFailureHandler"/>
<bean id="simpleUrlAuthenticationFailureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<constructor-arg name="defaultFailureUrl" value="/admin/login.jsp"></constructor-arg>
<property name="useForward" value="true" />
</bean>
结论:login-page
和 login-processing-url
最好不要设置相同的 URL