springSecurity的登录验证是由org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter这个过滤器来完成的,在该类的父类AbstractAuthenticationProcessingFilter中有一个AuthenticationManager接口属性,验证工作主如果经由过程这个AuthenticationManager接口的实例来完成的。在默认景象下,springSecurity框架会把org.springframework.security.authentication.ProviderManager类的实例注入到该属性,
AuthenticationManager接口的相干类图如下:
UsernamePasswordAuthenticationFilter的验证过程如下:
1. 起首过滤器会调用自身的attemptAuthentication办法,从request中取出authentication, authentication是在org.springframework.security.web.context.SecurityContextPersistenceFilter过滤器中经由过程捕获用户提交的登录表单中的内容生成的一个org.springframework.security.core.Authentication接话柄例.
2. 拿到authentication对象后,过滤器会调用ProviderManager类的authenticate办法,并传入该对象
3.ProviderManager类的authenticate办法再调用自身的doAuthentication办法,在doAuthentication办法中会调用类中的List<AuthenticationProvider> providers凑集中的各个AuthenticationProvider接话柄现类中的authenticate(Authentication authentication)办法进行验证,由此可见,真正的验证逻辑是由各个各个AuthenticationProvider接话柄现类来完成的,DaoAuthenticationProvider类是默认景象****入的一个AuthenticationProvider接话柄现类
4.AuthenticationProvider接口经由过程UserDetailsService来获取用户信息
以下为时序图:
处理form登陆的过滤器,与form登陆有关的所有操作都是在此进行的。
默认情况下只处理/j_spring_security_check请求,这个请求应该是用户使用form登陆后的提交地址,form所需的其他参数可以参考:
此过滤器执行的基本操作时,通过用户名和密码判断用户是否有效,如果登录成功就跳转到成功页面(可能是登陆之前访问的受保护页面,也可能是默认的成功页面),如果登录失败,就跳转到失败页面。
<form action="${pageContext.request.contextPath}/j_spring_security_check" style="width:260px;text-align:center;">
<fieldset>
<legend>登陆</legend>
用户: <input type="text" name="j_username" style="width:150px;" value="${sessionScope['SPRING_SECURITY_LAST_USERNAME']}"/><br />
密码: <input type="password" name="j_password" style="width:150px;" /><br />
<input type="checkbox" name="_spring_security_remember_me" />两周之内不必登陆<br />
<input type="submit" value="登陆"/>
<input type="reset" value="重置"/>
</fieldset>
</form>
源码:dofilter方法源码
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain)
/* */ throws IOException, ServletException
/* */ {
/* 184 */ HttpServletRequest request = (HttpServletRequest)req;
/* 185 */ HttpServletResponse response = (HttpServletResponse)res;
/* 187 */ if (!requiresAuthentication(request, response)) {
/* 188 */ chain.doFilter(request, response);
/* */
/* 190 */ return;
/* */ }
/* */
/* 193 */ if (this.logger.isDebugEnabled()) {
/* 194 */ this.logger.debug("Request is to process
authentication");
/* */ }
/* */ Authentication authResult;
/* */ try
/* */ {
/* 200 */ authResult = attemptAuthentication(request, response);
/* 201 */ if (authResult == null)
/* */ {
/* 203 */ return;
/* */ }
/* 205 */ this.sessionStrategy.onAuthentication(authResult,
request, response);
/* */ }
/* */ catch (AuthenticationException failed)
/* */ {
/* 209 */ unsuccessfulAuthentication(request, response, failed);
/* */
/* 211 */ return;
/* */ }
protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response)
/* */ {
/* 235 */ String uri = request.getRequestURI();
/* 236 */ int pathParamIndex = uri.indexOf(';');
/* */
/* 238 */ if (pathParamIndex > 0)
/* */ {
/* 240 */ uri = uri.substring(0, pathParamIndex);
/* */ }
/* */
/* 243 */ if ("".equals(request.getContextPath())) {
/* 244 */ return uri.endsWith(this.filterProcessesUrl);
/* */ }
/* */
/* 247 */ return uri.endsWith(request.getContextPath() + this.filterProcessesUrl);
/* */ }
如果请求url 的路径是j_spring_security_check 则检测
| /j_spring_security_check,提交登陆信息的URL地址。 自定义form时,要把form的action设置为/j_spring_security_check。注意这里要使用绝对路径,避免登陆页面存放的页面可能带来的问题。 |
| j_username,输入登陆名的参数名称。 |
| j_password,输入密码的参数名称 |
| _spring_security_remember_me,选择是否允许自动登录的参数名称。 可以直接把这个参数设置为一个checkbox,无需设置value,Spring Security会自行判断它是否被选中。 |