Oauth2.0 浅析和实践

本文详细介绍了OAuth2协议,包括其作用、设计思路、四种认证模式及其适用场景,重点展示了SpringSecurityOAuth2在实践中的应用,涉及令牌安全、有效期管理、CSRF防护和安全审计等方面。
摘要由CSDN通过智能技术生成

1 背景

公司内部应用通过CAS提供鉴权和授权服务,实现了单点登录。如果是第三方站点也需要单点登录,那就需要考虑如下问题:

  • 不可以向第三方暴露账号密码
  • 限制授权第三方应用获取的用户信息和权限范围

这个时候就需要OAuth2协议来帮助我们实现。

2 OAuth2是什么

OAuth(Open Authorization)是一个关于授权(authorization)的开放网络标准,允许用户授权第三方 应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他 们数据的所有内容。OAuth在全世界得到广泛应用,目前的版本是2.0版。
协议特点:

  • 简单:不管是OAuth服务提供者还是应用开发者,都很易于理解与使用;
  • 安全:没有涉及到用户密钥等信息,更安全更灵活;
  • 开放:任何服务提供商都可以实现OAuth,任何软件开发商都可以使用OAuth;

3 OAuth2的设计思路

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。"客户端"不能直接登 录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌 (token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期,"客户端"登 录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。
OAuth 2.0的运行流程如下图,摘自RFC 6749:

(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向授权服务器申请令牌。
(D)授权服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。

第三方应用申请令牌之前,都必须先到系统备案,说明自己的身份,然后会拿到两个 身份识别码:客户端 ID(client ID)和客户端密钥(client secret)。这是为了防止令牌被滥用,没有备案过的第三方应用,是不会拿到令牌的。

4. OAuth2的四种认证模式及适用场景

4.1 授权码模式

这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 WEB应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
认证过程:

(1) 客户端访问用户代理,后者将前者重定向到授权服务器 。
(2) 授权服务器认证客户端信息,并确定用户是否给予客户端授权。
(3) 用户给予授权,授权服务器将重定向事先指定的"重定向URI"(redirection URI),同时附上授权码。
(4) 客户端收到授权码,附上早先的"重定向URI",向授权服务器申请令牌。(客户端后台进行,无感知)
(5) 授权服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access_token)和更新令牌(refresh_token)。

适用场景:目前主流的第三方验证都是采用这种模式

4.2 简化(隐式)模式

有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端,这也增加了一定的风险。RFC 6749就规定了第二种方式,允许直接向前端颁发令牌,这种方式没有授权码这个中间步骤,所以称为(授权码)"隐藏式"(implicit)。
认证过程:

(1)客户端将用户导向授权服务器。
(2)用户决定是否给于客户端授权。
(3)假设用户给予授权,授权服务器将用户导向客户端指定的"重定向URI",并在URI的Hash部分包含了访问令牌。
(4)浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值。
(5)资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。
(6)浏览器执行上一步获得的脚本,提取出令牌。
(7)浏览器将令牌发给客户端。

适用场景:针对部分网站不存在后端,只有前端界面。

4.3 密码模式

如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为"密码式"。在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而授权服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。
认证过程:

(1)用户向客户端提供用户名和密码。
(2)客户端将用户名和密码发给授权服务器,向后者请求令牌。
(3)授权服务器确认无误后,向客户端提供访问令牌。

适用场景:自家公司搭建的授权服务器。

4.4 客户端模式

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行授权。
认证过程:

(1)客户端向授权服务器进行身份认证,并要求一个访问令牌。
(2)授权服务器确认无误后,向客户端提供访问令牌。

适用场景:没有前端的命令行应用,即在命令行下请求令牌。一般用来提供给我们完全信任的服务器端服务。

4.5 四种模式小结

四种模式时序图

授权码许可类型是流程最完备、安全性最高的授权方式。在选择授权类型时,优先考虑授权码模式,然后结合实际场景选择最适合的类型。

5 Spring Security-OAuth2的实践与挑战

Spring Security OAuth2是Spring Security框架的一个扩展模块,用于实现基于OAuth2协议的身份验证和授权功能。它提供了一套易于使用和集成的API,方便开发者在Spring应用程序中实现OAuth2的各种授权模式和流程,它使得开发者可以轻松地构建安全的OAuth2服务和客户端应用程序。
Spring Security OAuth2整体架构图:

基于实际的业务场景,我们选择了授权码模式实现。客户端在重定向 URI 中收到授权码,然后使用该授权码与授权服务器进行身份验证,并获取访问令牌。作为鉴权和授权平台,安全性是需放在第一位考虑的要素,安全性问题以及防护措施是重中之重,下面将关于Oauth几项安全挑战展开讨论。

5.1 令牌的安全传输

令牌在客户端和服务器之间传输时应进行安全加密,以防止令牌被拦截和篡改。可以使用HTTPS协议来保护令牌的传输安全。
在客户端与服务器建立连接时,客户端发送一个HTTPS请求。服务器会返回一个包含公钥的证书,客户端使用该公钥来加密对称密钥,并将加密后的密钥发送给服务器。服务器使用私钥解密对称密钥,并与客户端建立安全连接。可以通过配置Spring Security来启用HTTPS。首先,需要生成SSL证书,并将其配置到应用程序中。然后,在Spring Security的配置类中添加以下代码:

@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {        @Override    protected void configure(HttpSecurity http) throws Exception {        http.requiresChannel()                .anyRequest().requiresSecure();    }}

5.2 令牌的保密性

令牌应仅由授权服务器和资源服务器持有,并且不应通过客户端或其他不受信任的渠道传播。客户端应采取适当的安全措施,如存储令牌时进行加密处理。
Spring Security OAuth2可以在授权服务器和资源服务器中,配置加密算法和密钥来对令牌进行加密处理。授权服务器配置:

@Configuration@EnableAuthorizationServerpublic class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {     // 密钥存储在数据库或配置文件中    private static final String SECRET_KEY = "your-secret-key";     @Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        clients.inMemory()                .withClient("your-client-id")                .secret(SECRET_KEY)                .authorizedGrantTypes("password", "refresh_token")                .scopes("read", "write")                .accessTokenValiditySeconds(3600)                .refreshTokenValiditySeconds(86400);    }     @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {        endpoints.tokenStore(tokenStore());    }     @Bean    public TokenStore tokenStore() {        return new JwtTokenStore(accessTokenConverter());    }     @Bean    public JwtAccessTokenConverter accessTokenConverter() {        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();        converter.setSigningKey(SECRET_KEY);        return converter;    }}

资源服务器配置:

@Configuration@EnableResourceServerpublic class ResourceServerConfig extends ResourceServerConfigurerAdapter {     @Override    public void configure(HttpSecurity http) throws Exception {        http.authorizeRequests()                .antMatchers("/api/**").authenticated();    }}
 

5.3 令牌的有效期管理

令牌应具有适当的有效期,以限制其使用时间。令牌有效期过长可能导致安全隐患。
授权服务器应定期检查和清理过期的令牌,并提供令牌刷新机制,使客户端能够获取新的令牌。

Spring Security OAuth2可以通过配置来管理令牌的有效期:

@Configuration@EnableAuthorizationServerpublic class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {     // ...     @Autowired    private TokenStore tokenStore;     @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {        endpoints.tokenStore(tokenStore)                .tokenEnhancer(tokenEnhancerChain());    }     @Bean    public TokenEnhancerChain tokenEnhancerChain() {        TokenEnhancerChain chain = new TokenEnhancerChain();        chain.setTokenEnhancers(Arrays.asList(accessTokenConverter()));        return chain;    }}

5.4 跨站请求伪造(CSRF)攻击

客户端应采取适当的CSRF防护措施,如使用随机生成的令牌进行请求验证,以防止恶意站点利用受信任的用户凭据进行攻击。
可以通过Spring Security的CSRF防护功能来防止CSRF攻击:

@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {     @Override    protected void configure(HttpSecurity http) throws Exception {        http.csrf()                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());    }}

也可以通过在URL后添加随机生成的state参数,state参数能标记这是来自哪一个网站,且 state 参数是攻击者拿不到的,因此可以避免 CSRF 攻击。

5.5 频率限制和访问控制

授权服务器和资源服务器应实施适当的频率限制和访问控制策略,以防止恶意用户或恶意客户端对系统进行滥用和攻击。
在Spring Boot中,限制访问频率有多种方法:

(1)使用Spring Boot内置的应用拦截器:您可以通过实现HandlerInterceptor接口并将其注册为拦截器来实现该功能。
(2)使用Spring AOP:您可以使用Spring AOP创建切面并对特定的接口进行频率限制。
(3)使用Guava的RateLimiter:您可以使用Guava的RateLimiter类对特定的接口进行频率限制。
(4)使用第三方工具:您可以使用第三方工具(如Redis)来实现该功能。

具体实现方法取决于您的需求和项目特征。您可以根据您的需求选择最合适的方法。

5.6 安全审计和监控

系统应具备安全审计和监控机制,记录和监测与令牌相关的活动,以及检测和响应潜在的安全事件。
这里可以使用Spring Boot Actuator和其他安全审计工具来实现安全审计和监控。首先,添加所需的依赖项到项目的pom.xml文件中:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-security</artifactId></dependency>

然后,在application.properties或application.yml文件中配置安全审计和监控:

management.endpoints.web.exposure.include=*management.endpoint.health.show-details=alwaysmanagement.endpoint.auditevents.enabled=true

这样配置后,可以通过访问/actuator/auditevents端点来获取与令牌相关的审计事件信息。

5.7 安全存储凭证

客户端标识和客户端密钥应该被安全地存储,不应该被直接硬编码在客户端应用程序中。
定期轮换凭证,并限制授权服务器的访问,能够有效减少凭证泄漏带来的风险。

6 小结

通过上面的介绍,相信您对Oauth2.0的概念和如何使用有了初步的了解,希望本文能对您有所帮助。

  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值