Spring Security原理

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
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值