springcloud-alibaba springSecurity整合oauth2 授权码模式

OAuth的思路

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。“客户端"不能直接登录"服务提供商”,只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料

OAuth 2.0的运行流程如下图,摘自RFC 6749。
在这里插入图片描述
(A)用户打开客户端以后,客户端要求用户给予授权。

(B)用户同意给予客户端授权。

(C)客户端使用上一步获得的授权,向认证服务器申请令牌。

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

概述

Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于 Spring 的应用程序的事实标准。

Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架。像所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义需求

特征

  • 对身份验证和授权的全面且可扩展的支持
  • 防止会话固定、点击劫持、跨站点请求伪造等攻击
  • Servlet API 集成
  • 与 Spring Web MVC 的可选集成

工作原理
在这里插入图片描述

  1. 客户端发起一个请求,进入 Security 过滤器链。
  2. 当到 LogoutFilter 的时候判断是否是登出路径,如果是登出路径则到 logoutHandler ,如果登出成功则到logoutSuccessHandler 登出成功处理,如果登出失败则由 ExceptionTranslationFilter;如果不是登出路径则直接进入下一个过滤器。
  3. 当到 UsernamePasswordAuthenticationFilter的时候判断是否为登录路径,如果是,则进入该过滤器进行登录操作,如果登录失败则到 AuthenticationFailureHandler登录失败处理器处理,如果登录成功则到 AuthenticationSuccessHandler登录成功处理器处理,如果不是登录请求则不进入该过滤器。
  4. 当到 FilterSecurityInterceptor 的时候会拿到 uri ,根据 uri去找对应的鉴权管理器,鉴权管理器做鉴权工作,鉴权成功则到 Controller 层否则到 AccessDeniedHandler鉴权失败处理器处理。

OAuth 2.0授权框架定义了四种标准授权类型:授权码、隐式、资源所有者密码凭据和客户端凭据
AuthorizationGrantType
1.implicit
2.refresh_token
3.client_credentials
4.password
在这里插入图片描述
OAuth 定义了四个角色:

  • resource owner(资源所有者)

    能够授予对受保护资源的访问权限的实体。
    当资源所有者是一个人时,它被称为
    最终用户。

  • resource server(资源服务器)

    托管受保护资源的服务器,能够使用访问令牌接受
    和响应受保护资源请求。

  • client(客户端)

    代表
    资源所有者并经其授权发出受保护资源请求的应用程序。“客户”一词确实
    不暗示任何特定的实现特征(例如,
    应用程序是否在服务器、桌面或其他
    设备上执行)。

  • authorization server(授权服务器)
    服务器 在成功验证资源所有者并获得授权
    后向客户端颁发访问令牌。
    授权服务器和资源服务器之间的交互
    超出了本规范的范围。授权服务器
    可以是与资源服务器相同的服务器,也可以是单独的实体。
    单个授权服务器可以发布多个资源服务器
    接受的访问令牌。

授权码流程
流程包括以下步骤:

  • (A) 客户端通过将资源所有者的用户代理定向到授权端点来
    启动流程。客户端包括
    其客户端标识符、请求的范围、本地状态和 一旦授予
    (或拒绝)访问权限 ,授权服务器会将用户
     代理发送回该URI
    
  • (B) 授权服务器验证资源所有者(通过用户代理 )
    并确定资源所有者是允许还是拒绝客户端的访问请求。
    
  • (C) 假设资源所有者授予访问权限,授权服务器使用
    之前提供的重定向 URI(在请求中或在
    客户端注册期间)
    将用户代理重定向回客户端。重定向 URI 包括
    授权代码和客户端
    之前提供的任何本地状态。
    
  • (D) 客户端通过包含
    在上一步中收到
    的授权码,从授权服务器的令牌端点请求访问令牌。发出请求时,
    客户端向授权服务器进行身份验证。客户端
    包含用于获取授权的重定向URI验证码。
    
  • (E) 授权服务器对客户端进行身份验证,验证
    授权码,并确保接收到的重定向 URI与步骤 (C)
    中用于重定向客户端的 URI 匹配。如果有效,授权
    服务器 将使用访问令牌和可选的刷新令牌进行响应
    。
    . 授权请求客户端通过
    使用“application/x-www-form-urlencoded”格式
    将以下参数添加到授权端点 URI 的查询组件来构造请求 URI
    ,
    response_type
    REQUIRED.  Value MUST be set to "code".
    
    client_id
    REQUIRED.  The client identifier as described in Section 2.2.
    
    redirect_uri
    OPTIONAL.  As described in Section 3.1.2.
    

令牌端点TokenEndpoint
授权端点 AuthorizationEndpoint
用户授权提交端点 WhitelabelApprovalEndpoint

在这里插入图片描述

  1. 用户提交用户名、密码被SecurityFilterChain中的 UsernamePasswordAuthenticationFilter 过滤器获取到, 封装为请求Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。
  2. 然后过滤器将Authentication提交至认证管理器(AuthenticationManager)进行认证
  3. 认证成功后, AuthenticationManager 身份管理器返回一个被填充满了信息的(包括上面提到的权限信息, 身份信息,细节信息,但密码通常会被移除) Authentication 实例。
  4. SecurityContextHolder 安全上下文容器将第3步填充了信息的 Authentication ,通过 SecurityContextHolder.getContext().setAuthentication(…)方法,设置到其中。 可以看出AuthenticationManager接口(认证管理器)是认证相关的核心接口,也是发起认证的出发点,它 的实现类为ProviderManager。而Spring Security支持多种认证方式,因此ProviderManager维护着一个 List 列表,存放多种认证方式,最终实际的认证工作是由 AuthenticationProvider完成的。咱们知道web表单的对应的AuthenticationProvider实现类为 DaoAuthenticationProvider,它的内部又维护着一个UserDetailsService负责UserDetails的获取。最终 AuthenticationProvider将UserDetails填充至Authentication。
  5. UserDetailsService校验用户信息
  6. PasswordEncoder会去把数据库查到的密码(一般都是加盐后加密的密码)去进行校验(检查明文密码是否与之前的哈希值匹配)

JWT内容增强器配置
实现TokenEnhancer接口

package com.macro.mall.auth.component;

import com.macro.mall.auth.domain.SecurityUser;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * JWT内容增强器
 * Created by macro on 2020/6/19.
 */
@Component
public class JwtTokenEnhancer implements TokenEnhancer {
   
    /**
     * 在创建供客户端使用的新令牌的过程中,提供定制访问令牌的机会(例如,通过其附加信息映射)。
     * @param accessToken 当前访问令牌及其过期和刷新令牌
     * @param authentication 当前身份验证
     * @return 包括客户端和用户详细信息
     */
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
   
        SecurityUser securityUser = (SecurityUser) authentication.getPrincipal();
        Map<String, Object> info = new HashMap<>();
        //把用户ID设置到JWT中
        info.put("id", securityUser.getId());
        info.put("client_id",securityUser.getClientId());
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);
        return accessToken;
    }
}

SpringSecurity配置
继承WebSecurityConfigurerAdapter启动注解@EnableWebSecurity 打开security安全配置

package com.macro.mall.auth.config;

import org.aspectj.weaver.ast.And;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * SpringSecurity配置
 * Created by macro on 2020/6/19.
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
   

    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
//        包含所有执行器端点的匹配器。它还包括链接端点,该端点位于执行器端点的基本路径上
//        匹配"/rsa/publicKey"和"/v2/api-docs"规则的放行其他的都需要通过身份验证
        http.authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .antMatchers("/rsa/publicKey").permitAll()
                .antMatchers("/v2/api-docs").permitAll()
                .anyRequest().authenticated();
//      授权码模式必须配置 http.httpBasic();
        http.httpBasic();

    }

    @Bean
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值