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 securitypattern=“/**”:表示拦截所有资源access=“hasAnyRole('Role_USER')”:表示只有ROLE_USER角色才能访问资源- spring security默认的认证是必须加密的,加上
{noop}表示不加密认证
spring security 过滤链加载原理
- spring security过滤器链是通过
securityFilterChain这个类加载的
配置
认证信息
security:form-login:- login-page :指定登录页面
login-processiong-url:指定登录页面url地址default-target-url:指定登录成功后去的地址,一般是首页indexauthentication-failure:认证失败后跳转地址
退出
security:logoutlogout-url:指定退出页面logout-success-url:退出成功后的跳转页面
让认证页面可以匿名访问
security:intercept-url- pattern:
access="permitAll()":表示之后仍会进入过滤器链
释放静态资源
security:http:pattern="/css/**" security="none"pattern="/img/**" security="none"pattern="/plugins/**" security="none"
csrf (403 Forbidden)
-
去掉
csrf拦截的过滤器:隐患容易被csrf攻击security:csrf- disabled="true"
-
启用
csrf拦截,增加配置,保证登录请求被允许security:csrfInput
简单认证业务逻辑
UserDetailService
- spring security唯一认可的业务实现接口
UserDetails :Spring Security自己的用户对象
-
包含一些用于描述用户信息的方法
-
getAuthorities
获取用户包含的权限,返回权限集合,权限是一个继承了GrantedAuthority`的对象 -
getPassword
和getUsername`用于获取密码和用户名 -
isAccountNonExpired`方法返回boolean类型,用于判断账户是否未过期,未过期返回true反之返回false
-
isAccountNonLocked`方法用于判断账户是否未锁定
-
isCredentialsNonExpired用于判断用户凭证是否没过期,即密码是否未过期 -
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)
-
{noop}后面的密码,spring security会任务是原文 -
认证数据来源配置

-
加密(BCryptPasswordEncoder)
- 加盐加密
- 动态加密
security:password-encoder ref="passwordEncoder"
细化认证业务
设置用户状态
-
在用户简单认证业务中,我们封装User对象是,选择了三个构造参数的构造方法,其实还有另一个构造方法:

后四个布尔值的意义:
enabled:是否可用accountNonExpired:账户是否失效credentialsNonExpired:密码是否失效accountNonLocked:账户是否锁定
退出登录
- 注意:一旦开启了
csrf的防护功能,logout处理器便只支持POST请求方式了!
remember me
-
remember-me 基本实现(存在安全隐患)
- 页面提供复选框 name=“remember-me” value=“true/on/yes/1”
security:remember-me token-validity-seconds=“60”:开启remember me过滤器,设置token存储时间为60秒- 原理:创建记住我的token,将token写入到浏览器的cookie中
-
将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”:指定记住的参数名
-
显示当前认证用户名
-
从后台获取到当前认证通过后的用户名:
SecurityContextHolder.getContext().getAuthentication.getName()(SysUser(SecurityContextHolder.getContext().getAuthentication.getPrincipal())).getUsername -
<security:authentication property="principal.username"/><security:authentication property="username"/>
动态展示菜单
- 页面:
<security:authorize access="hasAnyRole('ROLE_PRODUCT','ROLE_ADMIN')"></security:authorize>
授权操作
-
开启权限注解支持
`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表达式注解 -
权限异常处理
Spring Security整合Spring Boot集中式版
初步整合认证
securityConfig(配置类)
extends WebSecurityConfigurerAdapter
- 指定认证用户来源 :
configure(AuthenticationManagerBuilder auth) - 配置
springSecurity相关信息:configure(HttpSecurity http)- 释放静态资源,指定资源拦截规则,指定自定义认证页面,指定退出认证配置
,``csrf跨域伪造请求配置
- 释放静态资源,指定资源拦截规则,指定自定义认证页面,指定退出认证配置
Spring Security整合Spring Boot分布式版
分布式认证概念
- 分布式认证,即我们常说的单点登录,简称
SSO,指的是在多应用系统项目中,用户只需要登录一次,就可以访问所有互相信任的应用系统
分布式认证流程图

- 总结,单点登录的实现分两大环节:
- 用户认证:主要是用户向认证服务器发起认证请求,认证服务器给用户返回一个成功的令牌token,主要在认证服务器中完成,即图中的A系统,注意A系统只能有一个
- 身份校验:这一环节使用户携带token去访问其他服务器时,在其他服务器中要对token的真伪进行校验,主要在资源服务器中完成,即图中的B系统,这里B系统可以有很多个。
JWT
概念
-
Json Web Token,一款出色的分布式身份校验方案,可以生成token,也可以解析token -
从分布式认证流程中,起关键作用的就是token,token的安全与否,直接关系到系统的健壮性,这里我们选择使用
JWT来实现token的生成和校验 -
JWT生成的token由三部分组成:- 头部:主要设置一些规范信息,签名部分的编码格式在头部中声明
- 载荷:token中存放有效信息的部分,比如用户名,用户角色,过期时间等,但是不要放密码,会泄露!
- 签名:将头部与载荷分别采用
base64编码后,用“.”相连,再加入盐,最后使用头部声明的编码类型进行编码,就得到签名。
-
JWT生成token的安全性分析从
JWT生成的token组成上来看,想要避免token被伪造,主要就得看签名部分了,而签名部分又有三部分组成,其中头部和载荷的base64编码,几乎透明的,毫无安全性可言,那么最终守护token安全的重担就全落在了加入的盐上面了。这是就需要对盐采用非对称加密的方式进行加密,以达到生产token与校验token方所用的盐不一致的安全效果。
非对称加密RSA
-
基本原理:同时生成两把密钥:私钥与公钥,私钥隐秘保存,公钥可以下发给信任客户端
- 私钥加密:持有私钥或公钥才可以解密
- 公钥加密:持有私钥才可以解密
-
优点:安全,难以解码
-
缺点:算法比较耗时,为了安全,可以接受
-
历史:三位数学家
Rivest、Shamir和Adleman设计了一种算法,可以实现非对称加密,这种算法用他们三个人的名字缩写:RSA
JWT相关工具类
OAuth2.0介绍
概念说明
OAuth是Open AuthorizationOAuth协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAuth的授权不会使第三方触及到用户的账号信息(如用户名与密码),即第三方无需使用用户名与密码就可以申请获取该用户资源的授权,因此OAuth是安全的。OAuth2.0是OAuth协议的延续版本,但不向前兼容(即完全废弃了OAuth1.0)- OAuth是一种用来规范令牌(Token)发放的授权机制,主要包含了四种授权模式:授权码模式、简化模式、密码模式和客户端模式。Spring Security OAuth2对这四种授权模式进行了实现
四种授权模式
-
在了解这四种授权模式前,我们需要先学习一些和OAuth相关的名词。举个社交登录的例子:比如在浏览器上使用QQ账户登录虎牙直播,这个过程可以提取出以下几个名词:
- Third-party application 第三方应用程序,比如这里的虎牙直播
- HTTP service HTTP服务提供商,比如这里的QQ(腾讯)
- Resource Owner 资源所有者,就是QQ的所有人,你
- User Agent 用户代理,这里指浏览器
- Authorization server 认证服务器,这里指QQ提供的第三方登录服务
- Resource server 资源服务器,这里指虎牙直播提供的服务,比如高清直播,弹幕发送等(需要认证后才能使用)
-
认证服务器和资源服务器可以在同一台服务器上,比如前后端分离的服务后台,它既提供认证服务(认证服务器、提供令牌),客户端通过令牌来从后台获取服务(资源服务器);它们可以不在同一台服务器上,比如第三方登录的例子
-
大致了解了这几个名词后,我们开始了解四种授权模式
-
授权码模式
- 是最能提现OAuth2协议,最严格,流程最完整的授权模式,流程如下所示:

-
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,必选项。
-
密码模式
-
在密码模式中,用户像客户端提供用户名和密码,客户端通过用户名和密码到认证服务器获取令牌。流程如下所示:

-
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协议发放令牌认证的方式来保护我们的资源