升级到Spring Security 4.2的坑及解决办法

2022-06-16 09:46:29

把框架从Spring Security从3升级到4,结果出现了一大堆错误,每一个都是巨坑,几个非常熟悉的问题,花了我几乎一整天的时间,下面一一说来。

1. 验证始终无法通过

输入正确的用户名与密码,却始终收到这样的异常:

org.springframework.security.authentication.BadCredentialsException: Bad credentials
    at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:151)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:174)
    at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:199)

把密码、密码加密器验证了好多遍,依旧存在这样的问题,后来追踪源码才发现,对于表单验证,Spring Security 4.2不支持参数更改,即用户名与密码必须为”username”与”password”,如果按照惯例,改为”j_username”与”j_password”,则验证无法通过。

<!-- 这两个参数配置现在无效 --><form-loginpassword-parameter="j_password"username-parameter="j_username"/>

2. session was not found

在提交表单验证账户合法性时,又出现如下错误:

HTTP Status403 - Couldnot verifythe provided CSRFtoken because your session wasnot found.

type Status report

message Couldnot verifythe provided CSRFtoken because your session wasnot found.

description Accesstothe specified resource has been forbidden.

错误很明显,是由于CSRF token引起的Session错误,解决办法很简单,禁止CSRF验证即可,如下:

<http><intercept-urlpattern="/login/*"access="IS_AUTHENTICATED_ANONYMOUSLY"/><intercept-urlpattern="/app/**"access="hasRole('USER')" /><!-- 必须添加此段声明,禁用CSRF功能 --><csrfdisabled="false"/><form-loginauthentication-success-forward-url="/app/home"authentication-failure-forward-url="/app/login/fail"always-use-default-target="false"default-target-url="/app/home"login-page="/index.html"login-processing-url="/login/check"/><logoutinvalidate-session="true"logout-url="/login/out"/></http>

3. 无法找到验证地址

按照以往的配置,现在竟然找不到验证地址,提交验证表单时,j_spring_check竟然报404错误,配置如下:

<form-loginlogin-page="/sti/login/index"login-processing-url="/app/j_spring_check"password-parameter="j_password"username-parameter="j_username"authentication-failure-forward-url="/app/login/fail"authentication-success-forward-url="/sti/home"default-target-url="/sti/home"always-use-default-target="false"/><!-- Spring Security filter的配置如下 --><filter><filter-name>springSecurityFilterChain</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class></filter><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/app/*</url-pattern></filter-mapping><!-- Spring MVC过滤器的配置如下 --><servlet><servlet-name>stixuDispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>
                META-INF/application-mvc-context.xml</param-value></init-param><load-on-startup>10</load-on-startup></servlet><servlet-mapping><servlet-name>stixuDispatcher</servlet-name><url-pattern>/app/*</url-pattern></servlet-mapping>

仔细诊断原因,/app/j_spring_check竟然被转发到Spring MVC进行处理,Servlet的优先级竟然比Filter还高,这完全不可能啊!

换成其他地址/sti/j_spring_check,直接报404错误,这很好理解,因为过滤器只拦截/app/*相关的请求,所以最后的解决办法如下:

  1. 首先修改web.xml文件
<!-- web.xml文件 --><filter><filter-name>springSecurityFilterChain</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class></filter><!-- 改为拦截所有请求 --><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern></filter-mapping>
  1. 修改Spring Security配置文件,将地址映射到根路径,如下:
<form-loginauthentication-success-forward-url="/app/login/success"authentication-failure-forward-url="/app/login/fail"always-use-default-target="false"default-target-url="/app/login/success"login-page="/app/login/index"
<!-- 修改到根路径,避免映射到SpringMVC-->                 login-processing-url="/login/check"/>

4. 总结

Spring Security的安全解决方案非常完善,升级到4.3版本后,功能更加强大了,配置更加简单与方便了,但与Spring Security 3的差异较大,应用时需要特别注意。

  • 作者:蚁方阵
  • 原文链接:https://blog.csdn.net/yiifaa/article/details/71744120
    更新时间:2022-06-16 09:46:29