spring security使用与分析

  • 前提

        使用spring-boot(1.5.10.RELEASE) 和spring-security(4.2.4.RELEASE)作为依赖环境

        通过maven构建项目 ,idea开发环境

  • 构建项目

        34c9d17b4560d7acbb235ef15b49ab81ad1.jpg

        通过spring initializr向导,选择需要的模块后新建项目,但是要注意,这种方式构建的项目使用的都是最新的jar,项目新建完成后将pom进行适当的修改,引入 以下两个依赖:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>1.5.10.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-bom</artifactId>
            <version>4.2.4.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

不通过parent来处理依赖库的版本问题 ,这样我觉得更灵活,可以解决多模块的parent问题。

  • 启动项目

        现在可以启动项目了,但是由于没有服务,没有界面,所以可能效果表现上不是很好,建一个controller

@RestController
public class SecController {

    @GetMapping("/hello")
    public String hello(){
        return "hello security!";
    }
}

启动项目后访问 http://localhost:8080/hello

进入这样一个界面,同时看到请求变成了login,为什么这样,之后解释,

422785009c2d42c3a6629cb073d7a67caf7.jpg

输入用户名:user,密码:项目 启动是控制台可见

636836c2e52be3767d3e374910268cc9140.jpg

登录后则进入了预想效果:

3bb1531a4f7757f76046f64518bb3c5c5aa.jpg

  • 分析

    首先我们要知道spring-security实现网络资源的权限是通过Filter实现,而对接口的权限的访问控制则是通过AOP。在我们发生请求/hello时,由于没有认证,被过滤器拦截。在启动日志中可以看到这样一句话:

Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5073b38b, org.springframework.security.web.context.SecurityContextPersistenceFilter@dbd5b3d, org.springframework.security.web.header.HeaderWriterFilter@4f8256c6, org.springframework.security.web.csrf.CsrfFilter@3006ebb, org.springframework.security.web.authentication.logout.LogoutFilter@7a1f1a0, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@21db4147, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@268f3fa9, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@4efca98c, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@2c67ca1d, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7d92a672, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@12eb1f47, org.springframework.security.web.session.SessionManagementFilter@7107591f, org.springframework.security.web.access.ExceptionTranslationFilter@5ff8d4d0, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@d3c5876]

主要说明了系统启动时,默认注册了哪些过滤器,那么在我们执行请求的时候,则会按照这个先后顺序执行,为什么最终会定位到/login这样一个请求并返回那样的登录界面呢?

通过断点发现,在没有认证时,认证过程中也就是经过上面的过滤器时出现异常,进而被ExceptionTranslationFilter拦截并处理处理,而实际的吹过程其实是由AuthenticationEntryPoint完成,默认情况配置了LoginUrlAuthenticationEntryPoint和BasicAuthenticationEntryPoint,可以看到相关的处理逻辑,最终其实是在LoginUrlAuthenticationEntryPoint处理,完成跳转到登录页面的处理。

那么具体的处理流程是怎样的呢?

1、用户通过浏览器发送请求,如果没有认证则交由AuthenticationEntryPoint处理;如果认证但无权限交由AccessDeniedHandler处理

2、经过上一步处理后,一般都会重定向到登录界面,需要注意的是,默认情况会下,/login对应的登录界面是由系统生成,见DefaultLoginPageConfigurer

3、此时用户输入用户名密码(或者认证id)

4、经由AbstractAuthenticationProcessingFilter,具体由哪一个类来处理,取决于我们在表单提交时的请求路径,比如默认情况我们提交【/logtin POST】,那么则会交由UsernamePasswordAuthenticationFilter,件构造器new AntPathRequestMatcher("/login", "POST"))

5、调用attemptAuthentication方法,构建Authentication,同样默认实现JaasAuthenticationToken,其实也就是用户令牌,主要包含了用户身份、证明、权限等信息,当然还有一个关键点则是UserDetails。

6、之后则是通过AuthenticationManager找到对应实现ProviderManager(默认 ),进而通过AuthenticationProvider找到适配对应Authentication类型的处理实现,最终通过UserDetailsService通过用户名构建UserDetails并设置到Authentication中。

7、最后则是在AuthenticationManager中完成用户的身份认证。

8、而权限验证则是通过AccessDecisionManager来完成,可以看到其实现类,提供了三种验证策略。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值