Spring Security

1,040 阅读10分钟

Spring Security

初识Spring Security

Spring Security概念

  • Spring Security是Spring采用AOP思想,基于servlet过滤器实现的安全框架,它提供了完善的认证机制和方法级的授权功能,是一款非常优秀的权限管理框架

Spring Security主要jar包及功能介绍

  • spring-security-core.jar :核心包,任何Spring Security功能都需要此包
  • spring-security-web.jar :web工程必备,包含过滤器和相关的Web安全基础结构代码
  • spring-security-config.jar:用于解析XML配置文件,用到spring Security的xml配置文件就要用到此包
  • spring-security-taglibs.jar :Spring Security提供的动态标签库,jsp页面可用

配置参数说明

  • auto-config="true" :自动加载spring security的配置文件
  • use-expressions=“true” :使用spring的EL表达式来配置spring security
  • pattern=“/**” :表示拦截所有资源
  • access=“hasAnyRole('Role_USER')” :表示只有ROLE_USER角色才能访问资源
  • spring security默认的认证是必须加密的,加上{noop}表示不加密认证

spring security 过滤链加载原理

  • spring security过滤器链是通过securityFilterChain这个类加载的

配置

认证信息

  • security:form-login:
    1. login-page :指定登录页面
    2. login-processiong-url:指定登录页面url地址
    3. default-target-url:指定登录成功后去的地址,一般是首页index
    4. authentication-failure:认证失败后跳转地址

退出

  • security:logout
    1. logout-url:指定退出页面
    2. logout-success-url:退出成功后的跳转页面

让认证页面可以匿名访问

  • security:intercept-url
    1. pattern:
    2. access="permitAll()":表示之后仍会进入过滤器链

释放静态资源

  • security:http :
    1. pattern="/css/**" security="none"
    2. pattern="/img/**" security="none"
    3. pattern="/plugins/**" security="none"

csrf (403 Forbidden)

  • 去掉csrf拦截的过滤器:隐患容易被csrf攻击

    security:csrf

    1. disabled="true"
  • 启用csrf拦截,增加配置,保证登录请求被允许

    1. security:csrfInput

简单认证业务逻辑

UserDetailService

  • spring security唯一认可的业务实现接口

UserDetails :Spring Security自己的用户对象

  • 包含一些用于描述用户信息的方法

    1. getAuthorities获取用户包含的权限,返回权限集合,权限是一个继承了GrantedAuthority`的对象

    2. getPasswordgetUsername`用于获取密码和用户名

    3. isAccountNonExpired`方法返回boolean类型,用于判断账户是否未过期,未过期返回true反之返回false

    4. isAccountNonLocked`方法用于判断账户是否未锁定

    5. isCredentialsNonExpired用于判断用户凭证是否没过期,即密码是否未过期

    6. isEnabled方法用于判断用户是否可用

  • return null:spring security` 会认为认证失败

  • return userDetails`: 认证成功

    • List<SimpleGrantedAuthority> authorities=new ArrayList<>()

    • authorities.add(new SimpleGrantedAuthority("ROLE_USER"))

    • UserDetail userDetail=new User(user.getUsername,"{noop}"+user.getPassword,authorities)

    1. {noop}后面的密码,spring security会任务是原文

    2. 认证数据来源配置

加密(BCryptPasswordEncoder)

  • 加盐加密
  • 动态加密
  • security:password-encoder ref="passwordEncoder"

细化认证业务

设置用户状态

  • 在用户简单认证业务中,我们封装User对象是,选择了三个构造参数的构造方法,其实还有另一个构造方法:

    后四个布尔值的意义:

    1. enabled:是否可用
    2. accountNonExpired:账户是否失效
    3. credentialsNonExpired:密码是否失效
    4. accountNonLocked:账户是否锁定

退出登录

  • 注意:一旦开启了csrf的防护功能,logout处理器便只支持POST请求方式了!

remember me

  1. remember-me 基本实现(存在安全隐患)

    • 页面提供复选框 name=“remember-me” value=“true/on/yes/1”
    • security:remember-me token-validity-seconds=“60” :开启remember me过滤器,设置token存储时间为60秒
    • 原理:创建记住我的token,将token写入到浏览器的cookie中
  2. 将token持久化到数据库

    • security:remember-me

      data-source-ref="dataSource"

      token-validity-seconds=“60”

      remember-me-parameter="remember-me"

      开启remember me过滤器
      

    ​ data-source-ref:指定数据库连接池

    ​ token-validity-seconds:设置token存储时间为60s

    ​ remember-me-parameter=“remember-me”:指定记住的参数名

显示当前认证用户名

  1. 从后台获取到当前认证通过后的用户名:

    SecurityContextHolder.getContext().getAuthentication.getName()

    (SysUser(SecurityContextHolder.getContext().getAuthentication.getPrincipal())).getUsername

  2. <security:authentication property="principal.username"/>

    <security:authentication property="username"/>

动态展示菜单

  1. 页面:<security:authorize access="hasAnyRole('ROLE_PRODUCT','ROLE_ADMIN')"></security:authorize>

授权操作

  1. 开启权限注解支持

     `secured-annotations="enabled" `:`springSecurity`内部的权限控制注解开关
    

    pre-post-annotations="enabled":spring指定的权限控制注解开关

    jsr250-annotations="enabled": 开启java250注解支持

    <security:global-method-security

    secured-annotations="enabled"

    pre-post-annotations="enabled"

    jsr250-annotations="enabled"

    />

    注解: @Secured({"ROLE_PRODUCT","ROLE_ADMIN"}) //spring security内部制定的注解

    @RoleAllowed({"ROLE_PRODUCT","ROLE_ADMIN"}) //jsr250注解

    @PreAuthorize(“hasAnyAuthority('ROLE_PRODUCT','ROLE_ADMIN')”) //springEL表达式注解

  2. 权限异常处理

Spring Security整合Spring Boot集中式版

初步整合认证

securityConfig(配置类)

extends WebSecurityConfigurerAdapter
  1. 指定认证用户来源 :configure(AuthenticationManagerBuilder auth)
  2. 配置springSecurity相关信息:configure(HttpSecurity http)
    • 释放静态资源,指定资源拦截规则,指定自定义认证页面,指定退出认证配置,``csrf跨域伪造请求配置

Spring Security整合Spring Boot分布式版

分布式认证概念

  • 分布式认证,即我们常说的单点登录,简称SSO,指的是在多应用系统项目中,用户只需要登录一次,就可以访问所有互相信任的应用系统

分布式认证流程图

  • 总结,单点登录的实现分两大环节:
    1. 用户认证:主要是用户向认证服务器发起认证请求,认证服务器给用户返回一个成功的令牌token,主要在认证服务器中完成,即图中的A系统,注意A系统只能有一个
    2. 身份校验:这一环节使用户携带token去访问其他服务器时,在其他服务器中要对token的真伪进行校验,主要在资源服务器中完成,即图中的B系统,这里B系统可以有很多个。

JWT

概念

  • Json Web Token,一款出色的分布式身份校验方案,可以生成token,也可以解析token

  • 从分布式认证流程中,起关键作用的就是token,token的安全与否,直接关系到系统的健壮性,这里我们选择使用JWT来实现token的生成和校验

  • JWT生成的token由三部分组成:

    1. 头部:主要设置一些规范信息,签名部分的编码格式在头部中声明
    2. 载荷:token中存放有效信息的部分,比如用户名,用户角色,过期时间等,但是不要放密码,会泄露!
    3. 签名:将头部与载荷分别采用base64编码后,用“.”相连,再加入盐,最后使用头部声明的编码类型进行编码,就得到签名。
  • JWT生成token的安全性分析

    JWT生成的token组成上来看,想要避免token被伪造,主要就得看签名部分了,而签名部分又有三部分组成,其中头部和载荷的base64编码,几乎透明的,毫无安全性可言,那么最终守护token安全的重担就全落在了加入的盐上面了。这是就需要对盐采用非对称加密的方式进行加密,以达到生产token与校验token方所用的盐不一致的安全效果。

非对称加密RSA

  • 基本原理:同时生成两把密钥:私钥与公钥,私钥隐秘保存,公钥可以下发给信任客户端

    1. 私钥加密:持有私钥或公钥才可以解密
    2. 公钥加密:持有私钥才可以解密
  • 优点:安全,难以解码

  • 缺点:算法比较耗时,为了安全,可以接受

  • 历史:三位数学家Rivest、Shamir和Adleman设计了一种算法,可以实现非对称加密,这种算法用他们三个人的名字缩写:RSA

JWT相关工具类

OAuth2.0介绍

概念说明

  • OAuth是Open Authorization
  • OAuth协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAuth的授权不会使第三方触及到用户的账号信息(如用户名与密码),即第三方无需使用用户名与密码就可以申请获取该用户资源的授权,因此OAuth是安全的。
  • OAuth2.0OAuth协议的延续版本,但不向前兼容(即完全废弃了OAuth1.0
  • OAuth是一种用来规范令牌(Token)发放的授权机制,主要包含了四种授权模式:授权码模式、简化模式、密码模式和客户端模式。Spring Security OAuth2对这四种授权模式进行了实现

四种授权模式

  • 在了解这四种授权模式前,我们需要先学习一些和OAuth相关的名词。举个社交登录的例子:比如在浏览器上使用QQ账户登录虎牙直播,这个过程可以提取出以下几个名词:

    1. Third-party application 第三方应用程序,比如这里的虎牙直播
    2. HTTP service HTTP服务提供商,比如这里的QQ(腾讯)
    3. Resource Owner 资源所有者,就是QQ的所有人,你
    4. User Agent 用户代理,这里指浏览器
    5. Authorization server 认证服务器,这里指QQ提供的第三方登录服务
    6. Resource server 资源服务器,这里指虎牙直播提供的服务,比如高清直播,弹幕发送等(需要认证后才能使用)
  • 认证服务器和资源服务器可以在同一台服务器上,比如前后端分离的服务后台,它既提供认证服务(认证服务器、提供令牌),客户端通过令牌来从后台获取服务(资源服务器);它们可以不在同一台服务器上,比如第三方登录的例子

  • 大致了解了这几个名词后,我们开始了解四种授权模式

  • 授权码模式

    1. 是最能提现OAuth2协议,最严格,流程最完整的授权模式,流程如下所示:

  1. A. 客户端将用户导向认证服务器;
    
    B. 用户决定是否给客户端授权;
    
    C. 同意授权后,认证服务器将用户导向客户端提供的URL,并附上授权码;
    
    D. 客户端通过重定向URL和授权码到认证服务器换取令牌;
    
    E. 校验无误后发放令牌。
    
    其中A步骤,客户端申请认证的URI,包含以下参数:
    
    response_type:表示授权类型,必选项,此处的值固定为”code”,标识授权码模式
    
    client_id:表示客户端的ID,必选项
    
    redirect_uri:表示重定向URI,可选项
    
    scope:表示申请的权限范围,可选项
    
    state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。
    
    D步骤中,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:
    
    grant_type:表示使用的授权模式,必选项,此处的值固定为”authorization_code”。
    
    code:表示上一步获得的授权码,必选项。
    
    redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
    
    client_id:表示客户端ID,必选项。
    
  • 密码模式

    1. 在密码模式中,用户像客户端提供用户名和密码,客户端通过用户名和密码到认证服务器获取令牌。流程如下所示:

    2. A. 用户向客户端提供用户名和密码;
      
      B. 客户端向认证服务器换取令牌;
      
      C. 发放令牌。
      
      B步骤中,客户端发出的HTTP请求,包含以下参数:
      
      grant_type:表示授权类型,此处的值固定为”password”,必选项。
      
      username:表示用户名,必选项。
      
      password:表示用户的密码,必选项。
      
      scope:表示权限范围,可选项。
      

Spring Security OAuth2

  • Spring框架对OAuth2协议进行了实现,下面学习下上面两种模式在Spring Security OAuth2相关框架的使用。

    Spring Security OAuth2主要包含认证服务器和资源服务器这两大块的实现:

  • 认证服务器主要包含了四种授权模式的实现和Token的生成与存储,我们也可以在认证服务器中自定义获取Token的方式(后面会介绍到);资源服务器主要是在Spring Security的过滤器链上加了OAuth2AuthenticationProcessingFilter过滤器,即使用OAuth2协议发放令牌认证的方式来保护我们的资源