Spring Security
Spring Security的核心思想是用户授权和资源认证。认证访问系统的用户,而授权则是用户可以访问的资源。
- 认证是调用authenticationManager.authenticate()方法来获得证书authentication,一般我们采用用户名、密码方式认证,那么authentication的实现类就是UsernamePasswordAuthentication。
- 授权是让用户可以访问哪些资源,一般在WebSecurityConfigurerApdater的继承类中编写。
通过用户名、密码验证后获取信息Authentication认证信息,将此信息存入session中保存。以后每次访问都通过session中的属性SPRING_SECURITY_CONTEXT获取Authentication作为通行证。
Spring OAuth2.0
OAuth 2.0 的认证流程如下:
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
(A)用户打开客户端以后,客户端请求资源所有者(用户)的授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请访问令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放访问令牌。
(E)客户端使用访问令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
其中,用户授权有四种模式:
- 授权码模式(authorization code)--即先登录获取code,再获取token。
- 简化模式(implicit)— 简化模式(在redirect_uri 的Hash传递token; Auth客户端运行在浏览器中,如JS,Flash)。
- 密码模式(resource owner password credentials)--将用户名,密码传过去,直接获取token。
- 客户端模式(client credentials)— 客户端模式(无用户,用户向客户端注册,然后客户端以自己的名义向’服务端’获取资源)。
OAuth 2.0 主要有4类角色:
- resource owner:资源所有者,指终端的“用户”(user)。
- resource server:资源服务器,即服务提供商存放受保护资源。访问这些资源,需要获得访问令牌(access token)。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。比如我们访问新浪博客网站,如果使用新浪博客的账号来登录新浪博客网站,那么新浪博客的资源和新浪博客的认证都是同一家,可以认为是同一个服务器。如果是新浪博客账号去登录了知乎,那么显然知乎的资源和新浪的认证不是一个服务器。
- client:客户端,代表向受保护资源进行资源请求的第三方应用程序。
- authorization server: 授权服务器, 在验证资源所有者并获得授权成功后,将发放访问令牌给客户端。
OAuth 2.0 一般分为两个部分,一部分是提供方(Provider)[通常指服务提供方],另一部分则是客户端(Client)。
OAuth 2.0 提供方
OAuth 2.0 提供方通过某种机制来提供受 OAuth 2.0 保护的资源。其配置涉到确立 OAuth 2.0 客户端能做什么,是能独立访问受保护的资源,还是保护用户的利益。提供方通过管理和验证 OAuth 2.0 令牌达到目的,令牌就是用来访问受保护资源的。在某些情况下,提供方还必须为用户提供一个接口用于确认授权客户端访问受保护的资源(比如,确认页面)。
OAuth 2.0 提供方实现
OAuth 2.0 的提供方实际涵盖两个角色,即认证服务 (Authorization Server) 和资源服务 (Resource Server),有时候它们会在同一个应用程序中实现。使用 Spring Security OAuth 的时候你可以选择把把它们分别放在两个应用程序中,也可以选择建立使用同一个认证服务的多个资源服务。对令牌的请求由 Spring MVC 控制器终端进行处理,而标准的 Spring security 请求过滤器会处理对受保护资源的访问。
Spring Security 过滤器链需要以下各端来实现 OAuth 2.0 认证服务(Authorization Server):
- AuthorizationEndpoint 服务于认证请求, 根据用户认证获得授权码。默认 URL:
- POST /oauth/authorize
- GET /oauth/authorize
- TokenEndpoint 服务于访问令牌的请求。默认 URL: /oauth/token。
- GET /oauth/token?grant_type=password #请求授权token
- GET /oauth/token?grant_type=refresh_token #刷新token
- CheckTokenEndpoint 校验token,可以用于远程解码令牌 。默认 URL:
- GET/POST /oauth/check_token?token=ox23232323
- WhitelabelApprovalEndpoint 显示授权服务器的确认页,默认 URL:
- GET /oauth/confirm_access
- WhitelabelErrorEndpoint 显示授权服务器的错误页
- GET /oauth/error
一般情况下,创建两个配置类,一个继承AuthorizationServerConfigurerAdapter,一个继承WebSecurityConfigurerAdapter,
再去复写里面的方法。
以上这些endpoint都在源码里的endpoint包里面。
下面的过滤器用于实现 OAuth 2.0 资源服务(Resource Server):
- OAuth2AuthenticationProcessingFilter: 给带有访问令牌的请求加载认证。 从request中提取access_token(BearTokenExtractor),构建PreAuthenticatedAuthenticationToken并验证,构建后的authentication参数如下:
tokenType="Bearer",
principal=token值。
再根据OAuth2AuthenticationManager验证该authentication的合法性。
TokenGranter 对应用户授权模式:
- ResourceOwnerPasswordTokenGranter :password密码模式
- AuthorizationCodeTokenGranter : authorization_code授权码模式
- ClientCredentialsTokenGranter : client_credentials客户端模式
- ImplicitTokenGranter : implicit简化模式
- RefreshTokenGranter :refresh_token 刷新token专用
- CompositeTokenGranter:组合TokenGranter , List<TokenGranter>,对应上述五种GrantType的实际授权实现。
使用token的方式有两种:
(1)Bearer Token(https传输方式保证传输过程的安全):主流
(2)Mac(http+sign)
Bearer Token (RFC 6750) 用于OAuth 2.0授权访问资源,任何Bearer持有者都可以无差别地用它来访问相关的资源,而无需证明持有加密key。一个Bearer代表授权范围、有效期,以及其他授权事项;一个Bearer在存储和传输过程中应当防止泄露,需实现Transport Layer Security (TLS);一个Bearer有效期不能过长,过期后可用Refresh Token申请更新。
资源请求
Bearer实现资源请求有三种方式:Authorization Header、Form-Encoded Body Parameter、URI Query Parameter,这三种方式优先级依次递减
Authorization Header:该头部定义与Basic方案类似
GET /resource HTTP/1.1
Host: server.example.com
Authorization: Bearer mF_9.B5f-4.1JqM
二. WWW-Authenticate头
在客户端未发送有效Bearer的情况下,即错误发生时,资源服务器须发送WWW-Authenticate头,下为示例:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example", error="invalid_token", error_description="The access token expired"
Security 过滤器链:
1.SecurityContextPersistenceFilter:与SecurityContext安全上下文信息有关
2.HeaderWriterFilter:给http响应添加一些Header
3.CsrfFilter:防止csrf攻击,默认开启
4.LogoutFilter:处理注销的过滤器
5.UsernamePasswordAuthenticationFilter:表单认证过滤器
6.RequestCacheAwareFilter:缓存request请求
7.SecurityContextHolderAwareRequestFilter:此过滤器对ServletRequest进行了一次包装,使得request具有更加丰富的API
8.AnonymousAuthenticationFilter:匿名身份过滤器
9.SessionManagementFilter:session相关的过滤器,常用来防止session-fixation protection attack,以及限制同一用户开启多个会话的数量
10.ExceptionTranslationFilter:异常处理过滤器
11.FilterSecurityInterceptor:web应用安全的关键Filter
ClientCredentialsTokenEndpointFilter: 从parameter中抽取client_id,client_secret信息,并进行client的身份验证
BasicAuthenticationFilter: parameter中没有客户端信息时从header Authorization Basic XXXX中抽取client信息,其中XXXX为Base64(clientId:clientSecret)。
Spring OAuth2官方原文:http://projects.spring.io/spring-security-oauth/docs/oauth2.html
Spring OAuth2介绍:https://www.oschina.net/translate/spring-security-oauth-docs-oauth2