赞
踩
Spring Security原理是通过使用过滤器Filter,实现责任链设计模式,通过预先configure(HttpSecurity http)设定责任链过滤规则实现认证和授权。
过滤器通过spring容器托管实现,需要使用代理DelegatingFilterProxy实现
FilterChainProxy 过滤器链代理,是通过DelegatingFilterProxy代理Spring容器中的对象。
官方文档中描述Filter列表包括
https://docs.spring.io/spring-security/site/docs/5.3.3.BUILD-SNAPSHOT/reference/html5/#modules
ChannelProcessingFilter ConcurrentSessionFilter WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter HeaderWriterFilter CorsFilter CsrfFilter LogoutFilter OAuth2AuthorizationRequestRedirectFilter Saml2WebSsoAuthenticationRequestFilter X509AuthenticationFilter AbstractPreAuthenticatedProcessingFilter CasAuthenticationFilter OAuth2LoginAuthenticationFilter Saml2WebSsoAuthenticationFilter UsernamePasswordAuthenticationFilter ConcurrentSessionFilter OpenIDAuthenticationFilter DefaultLoginPageGeneratingFilter DefaultLogoutPageGeneratingFilter DigestAuthenticationFilter BearerTokenAuthenticationFilter BasicAuthenticationFilter RequestCacheAwareFilter SecurityContextHolderAwareRequestFilter JaasApiIntegrationFilter RememberMeAuthenticationFilter AnonymousAuthenticationFilter OAuth2AuthorizationCodeGrantFilter SessionManagementFilter ExceptionTranslationFilter FilterSecurityInterceptor SwitchUserFilter
这些Filter列表中的内容与configure(HttpSecurity http)代码配置有关系,我跟踪的Filter包括如下,使用的Form登录
[
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1015a4b9,
org.springframework.security.web.access.ExceptionTranslationFilter@6d08b4e6,
org.springframework.security.web.header.HeaderWriterFilter@7bf01cb,
org.springframework.security.web.session.SessionManagementFilter@12b5736c,
org.springframework.security.web.context.SecurityContextPersistenceFilter@2cd4e16a,
org.springframework.security.web.savedrequest.RequestCacheAwareFilter@7b477141,
org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3625a016,
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@4364863,
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@267cde2e,
org.springframework.security.web.authentication.logout.LogoutFilter@1f1cddf3,
org.springframework.security.web.access.intercept.FilterSecurityInterceptor@46039a21
]
Configure方法代码
protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/org/**") .hasRole("ORG") .antMatchers("/user/**") .hasRole("USER") .antMatchers("/orguser/**") .access("hasRole('ORG') and hasRole('USER')") .antMatchers("/role/**") .access("hasAnyRole('ORG') and hasRole('ROLE')") .anyRequest() .authenticated() .and() .formLogin() .loginProcessingUrl("/logindone") .successHandler(new AuthenticationSuccessHandler() { //登陆成功后 @Override public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication auth) //当前用户登陆信息 throws IOException { Object principal = auth.getPrincipal(); resp.setContentType("application/json;charset=utf-8"); PrintWriter out = resp.getWriter(); resp.setStatus(200); Map<String, Object> map = new HashMap<>(); map.put("status", 200); map.put("msg", principal); ObjectMapper om = new ObjectMapper(); out.write(om.writeValueAsString(map)); out.flush(); out.close(); } }) .failureHandler(new AuthenticationFailureHandler() { //登陆失败后 @Override public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) //获取登陆失败原因 throws IOException { e.printStackTrace(); resp.setContentType("application/json;charset=utf-8"); PrintWriter out = resp.getWriter(); resp.setStatus(401); Map<String, Object> map = new HashMap<>(); map.put("status", 401); if (e instanceof LockedException) { map.put("msg", "账户被锁定,登录失败!"); } else if (e instanceof BadCredentialsException) { map.put("msg", "账户名或密码输入错误,登录失败!"); } else if (e instanceof DisabledException) { map.put("msg", "账户被禁用,登录失败!"); } else if (e instanceof AccountExpiredException) { map.put("msg", "账户已过期,登录失败!"); } else if (e instanceof CredentialsExpiredException) { map.put("msg", "密码已过期,登录失败!"); } else { map.put("msg", "登录失败!"); } ObjectMapper om = new ObjectMapper(); out.write(om.writeValueAsString(map)); out.flush(); out.close(); } }) .permitAll() .and() .logout()//开启注销登陆 .logoutUrl("/logout")//注销登陆请求url .clearAuthentication(true)//清除身份信息 .invalidateHttpSession(true)//session失效 .addLogoutHandler(new LogoutHandler() {//注销处理 @Override public void logout(HttpServletRequest req, HttpServletResponse resp, Authentication auth) { } }) .logoutSuccessHandler(new LogoutSuccessHandler() { //注销成功处理 @Override public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication auth) throws IOException { resp.sendRedirect("/login_page"); //跳转到自定义登陆页面 } }) .and() .csrf() .disable(); }
通过代码跟踪发现Form表单登录,后台使用会话记录登录状态,这些都可以配置,Spring Security提供了灵活配置方式。
登录成功后出现JSESSIONID cookie,如果将其删除,必须重新登录,跟踪其后台代码发现
package org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
初始化了会话关联Filter
package org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer
package org.springframework.security.web.session.SessionManagementFilter
package org.springframework.security.web.authentication.session.AbstractSessionFixationProtectionStrategy
判断每次请求是否已经登录是在这个Filter中实现
package org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。