Oauth2与Spring Security

Oauth2

1. Oauth2概念

    OAuth 是一个开放标准,该标准允许用户让第三方应用访问该用户在某一网站上存储的私密资源(如头像、照片、视频等),而在这个过程中无须将用户名和密码提供给第三方应用。实现这一功能是通过提供一个令牌(token),而不是用户名和密码来访问他们存放在特定服务提供者的数据

     每一个令牌授权一个特定的网站在特定的时段内访问特定的资源。这样,OAuth 让用户可以授权第三方网站灵活地访问存储在另外一些资源服务器的特定信息,而非所有内容。目前主流的 qq、微信等第三方授权登录方式都是基于 OAuth2 实现的

     OAuth 2 是 OAuth 协议的下一版本,但不向下兼容 OAuth 1.0。OAuth 2 关注客户端开发者的简易性,同时为 Web 应用、桌面应用、移动设备、起居室设备提供专门的认证流程。传统的 Web 开发登录认证一般都是基于 Session 的,但是在前后端分离的架构中继续使用Session 会有许多不便,因为移动端(Android、iOS、微信小程序等)要么不支持Cookie(微信小程序),要么使用非常不便,对于这些问题,使用 OAuth 2 认证都能解决。



2. OAuth2 授权流程

这里截了个图,来源在图中,假设是第三方应用申请微信或者qq授权登录流程,授权流程如图所示。

在这里插入图片描述

  • 步骤1:客户端(第三方应用,例如京东)跳转到要授权的页面,向用户请求授权。

    要授权的页面是例如QQ、微信的服务端开发的,和第三方应用无关,第三方只需传递它的客户端id和之后要重定向的地址。

  • 步骤2:用户单击服务授权页面上的同意授权按钮后,服务端(例如QQ、微信)进行校验用户身份,校验成功后重定向返回一个授权许可凭证给客户端。

    这里多一步返回验证码是因为code是重定向返回回来的,地址栏可以直接看到,如果直接返回的是token非常不安全,所以会返回一个验证码。

  • 步骤3:客户端把授权许可凭证传给客户端的服务器,由客户端的服务器携带自己的密码和授权许可凭证去向授权服务器申请令牌。

  • 步骤4:授权服务器验证信息无误后,发放令牌给客户端。

  • 步骤5:客户端拿着令牌去资源服务器访问资源。

  • 步骤6:资源服务器验证令牌无误后开放资源。

注意:

  1. OAuth2 授权码模式为什么不直接返回access_token
  2. 关于oauth2中为什么不直接返回token而是传授权码code
  3. 为什么OAuth2里面在获取access token之前一定要先获取code,然后再用code去获取access token?



3. OAuth2 角色

  • 资源所有者(Resource Owner):即代表授权客户端访问本身资源信息的用户,客户端访问用户帐户的权限仅限于用户授权的“范围”。

    用户、“我”。

  • 客户端(Client):即代表意图访问受限资源的第三方应用。在访问实现之前,它必须先经过用户者授权,并且获得的授权凭证将进一步由授权服务器进行验证。

    京东、微博等第三方应用。

  • 授权服务器(Authorization Server):授权服务器用来验证用户提供的信息是否正确,并返回一个令牌给第三方应用。

    QQ、微信等的授权服务器。

  • 资源服务器(Resource Server):资源服务器是提供给用户资源的服务器,例如头像、照片、视频等。

    QQ、微信等的资源服务器。



4 OAuth2 授权模式简介

后面会详细说明,这里先看看概念。

     OAuth 协议的授权模式共分为 4 种,分别说明如下:

  • 授权码模式授权码模式(authorization code)是功能最完整、流程最严谨的授权模式。它的特点就是通过客户端的服务器与授权服务器进行交互。

    上述授权流程就是授权码模式,国内常见的第三方平台登录功能基本都是使用这种模式。

  • 简化模式:简化模式不需要客户端的服务器参与,直接在浏览器中向授权服务器中请令牌。

    一般若网站是纯静态页面,则可以采用这种方式。

  • 密码模式:密码模式是用户把用户名密码直接告诉客户端,客户端使用这些信息向授权服务器中请令牌。

    这需要用户对客户端高度信任,例如客户端应用和服务提供商是同一家公司。

  • 客户端模式客户端模式是指客户端使用自己的名义而不是用户的名义向服务提供者申请授权。严格来说,客户端模式并不能算作 OAuth 协议要解决的问题的一种解决方案,但是,对于开发者而言,在一些前后端分离应用或者为移动端提供的认证授权服务器上使用这种模式还是非常方便的。

5. Spring Security Oauth2 入门案例

5.1 什么是Spring Security

    Spring Security是一套安全框架,可以基于RBAC(基于角色的权限控制)对用户的访问权限进行控制,核心思想是通过一系列的filter chain来进行拦截过滤,以及IoC和Aop,为web请求和方法调用提供身份确认和授权处理,避免了代码耦合,减少大量重复代码操作

    而Oauth2是一种协议规范,Spring Security Oauth2是对Oauth2的一种实现


5.2 搭建授权服务器

5.2.1 POM配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lijinghua</groupId>
    <artifactId>Oauth2-Server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Oauth2-Server</name>
    
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR5</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

5.2.2 编写启动器
@SpringBootApplication
@EnableResourceServer//开启资源服务器
public class Oauth2ServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(Oauth2ServerApplication.class, args);
    }
}

注意:授权服务器实际上也可以作为资源服务器。


5.2.3 Application.yml
server:
  port: 10000

5.2.4 Oauth2配置类
@Configuration
@EnableAuthorizationServer//开始授权服务
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {

    //认证管理器
    @Autowired
    private AuthenticationManager authenticationManager;

    private static final String CLIENT_ID = "cms";
    private static final String SECRET_CHAR_SEQUENCE = "{noop}secret";//{noop}表示对密码不加密,默认是加密的

    //授权范围
    private static final String SCOPE_READ = "read";
    private static final String SCOPE_WRITE = "write";
    private static final String TRUST = "trust";
    private static final String USER = "user";
    private static final String ALL = "all";

    private static final int ACCESS_TOKEN_VALIDITY_SECONDS = 30 * 60;
    private static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 30 * 60;
    // 密码授权模式
    private static final String GRANT_TYPE_PASSWORD = "password";
    //授权码模式
    private static final String AUTHORIZATION_CODE = "authorization_code";
    //refresh token模式
    private static final String REFRESH_TOKEN = "refresh_token";
    //简化授权模式
    private static final String IMPLICIT = "implicit";
    //指定哪些资源是需要授权验证的
    private static final String RESOURCE_ID = "resource_id";

    /**
     * 客户端信息配置
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()// 使用内存存储
                .withClient(CLIENT_ID)//标记客户端id
                .secret(SECRET_CHAR_SEQUENCE)//客户端安全码
                .autoApprove(true)//为true 直接自动授权成功返回code
                .redirectUris("http://127.0.0.1:10001/cms/login") //授权后重定向uri,这里写死了
                .scopes(ALL)//允许授权范围
                .accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)//token的有效期 时间/秒
                .refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS)//刷新token的有效期 时间/秒
                .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE);//允许授权类型
    }

    /**
     * 授权服务器端点的配置,设置token的存储方式
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 使用内存保存生成的token
        endpoints.authenticationManager(authenticationManager).tokenStore(memoryTokenStore());
    }

    /**
     * 认证服务器的安全配置
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                //.realm(RESOURCE_ID)
                // 开启/oauth/token_key端点,设置认证权限为令牌密钥访问
                .tokenKeyAccess("isAuthenticated()")
                // 开启/oauth/check_token端点,用于令牌验证的端口,设置认证权限为可直接访问
                // .checkTokenAccess("isAuthenticated()")
                .checkTokenAccess("permitAll()")
                //允许表单认证
                .allowFormAuthenticationForClients();
    }

    @Bean
    public TokenStore memoryTokenStore() {
        // 最基本的InMemoryTokenStore生成token
        return new InMemoryTokenStore();
    }
}


5.2.5 Spring Security配置类
@Configuration
@EnableWebSecurity//开启Spring Security配置
@Order(1)//Spring配置优先级
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { //auth.inMemoryAuthentication()
        auth.inMemoryAuthentication()
                .withUser("lijinghua")
                .password("{noop}123")
                .roles("admin");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers("/asserts/**");
        web.ignoring().antMatchers("/favicon.ico");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin().permitAll()// 配置登录页并允许访问
                // .and().httpBasic()// 配置Basic登录(弹窗)
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/")// 配置登出页面
                .and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**", "/api/**").permitAll()// 配置允许访问的链接
                .anyRequest().authenticated()// 其余所有请求全部需要鉴权认证
                .and().csrf().disable();// 关闭跨域保护;
    }
}

5.3 搭建资源服务器

5.3.1 POM配置文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                            https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.lijinghua</groupId>
    <artifactId>Oauth2-Server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Oauth2-Server</name>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR5</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

5.3.2 编写启动器
@SpringBootApplication
@EnableResourceServer//开启资源服务器
public class CmsApplication {
    public static void main(String[] args) {
        SpringApplication.run(CmsApplication.class, args);
    }
}

5.3.3 Application.yml
server:
  port: 10001
  servlet:
    context-path: /cms

5.3.4 Oauth2配置类
@Configuration
public class Oauth2ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private static final String CHECK_TOKEN_URL = "http://localhost:10000/oauth/check_token";
    
    /**
     * 配置使用授权服务器的令牌校验端点,对令牌进行校验
     * (这里只是学习测试,实际项目中用JWT,基于非对称密钥进行验证,因为每次都这样调用远程的令牌校验端点过于低效)
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        RemoteTokenServices tokenServices = new RemoteTokenServices();
        tokenServices.setCheckTokenEndpointUrl(CHECK_TOKEN_URL);
        tokenServices.setClientId("cms");
        tokenServices.setClientSecret("secret");

        resources.tokenServices(tokenServices);
    }
}


5.3.5 Spring Security配置类
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").authenticated();
        // 禁用CSRF
        http.csrf().disable();
    }
}

5.3.6 编写测试Controller层
@RestController
public class HelloController {

    /**
     * 获得当前登录对象
     * @param authentication
     * @return
     */
    @GetMapping("/getCurrentUser")
    public Object getCurrentUser(Authentication authentication) {
        return authentication;
    }

    @GetMapping("/index")
    public String index() {
        return "index";
    }
}

5.4 测试

    直接访问资源服务器上的资源,被提示未认证。

在这里插入图片描述


6 授权码模式

    授权码(authorization code)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。授权码模式是功能最完整、使用最广泛、流程最严密的授权模式。

下面借了个hxd的图,如第2节所述,授权码模式如图所示。

在这里插入图片描述

​ 第三方授权一般就是授权码模式,流程如下:

(A):客户端携带client_id、redirect_uri,中间通过代理者(比如浏览器)访问授权服务器,如果已经登录过了会直接重定向回redirect_uri,没有登录过就跳转到登录页面。

(B)授权服务器对客户端进行身份验证(通过用户代理,让用户输入用户名和密码并同意授权)。

(C)授权通过,会重定向到redirect_uri并携带授权码code作为uri参数。

(D)客户端携带授权码访问授权服务器索要令牌。

(E)验证授权码通过,返回令牌acceptToken。


6.1 授权服务器设置授权码模式

    在入门案例的Oauth2配置类中,我们已经在客户端的信息配置里配置了授权模式为允许的授权类型。

在这里插入图片描述


6.2 申请授权码

    访问授权链接,在浏览器访问(Get请求)就可以,授权码模式response_type参数传code:

http://localhost:10000/oauth/authorize?client_id=cms&client_secret=secret&response_type=code

    访问时可携带的参数:

  • client_id:客户端id,和授权配置类中设置的客户端id一致。

  • client_secret:我们在入门案例中设置了安全码,即客户端密钥(可选),所以这里需要传一个。

  • response_type:授权码模式固定为code。

  • scope:客户端被授权范围,和授权配置类中设置的scope一致。

  • redirect_uri:之后要重定向的uri,当授权码申请成功后会跳转到此地址,并在后边带上code参数(授权码) 。

    注意:这个地址我们这里测试的时候写死了。

    如果没登录。那么自动会跳转至SpringSecurity的默认登录页面http://localhost:10000/login,具体代码是 http.formLogin().permitAll(); 。如果要弹窗登录的,可以配置 http.httpBasic(); ,但是这种配置是没有登录页面的。自定义登录页面可以这样配置http.formLogin().loginPage("/login").permitAll()

在这里插入图片描述

    输入用户密码(这里测试是用写死在授权服务器后台的用户信息)并登录,即正常流程中的第三方网站跳转的授权服务器方的授权登录页面,然后点击授权登录。如果已经登录了,那么客户端会直接访问远程的授权服务器,申请授权码。

在这里插入图片描述

    由于这里是测试,使用了假的重定向地址,所以效果如下。但是我们可以清楚地看到,授权服务器在验证了用户身份之后,重定向到了我们申请返回的地址,并携带上了授权码。

在这里插入图片描述


6.3 申请令牌

    拿到授权码后,发送post请求申请令牌,这里使用Postman申请授权码。

在这里插入图片描述

  • grant_type:授权类型,填写authorization_code,表示授权码模式
  • code:授权码,就是刚刚获取的授权码,授权码只使用一次就无效了,需要重新申请。
  • redirect_uri:申请授权码时的跳转url,一定和申请授权码时用的redirect_uri一致。

    注意,此链接需要使用 http Basic认证。 什么是http Basic认证? http协议定义的一种认证方式,将客户端id和客户端密码按照“客户端ID:客户端密码”的格式拼接,并用base64编码,放在header中请求服务端

客户端Id和客户端密码会匹配数据库oauth_client_details表中的客户端id及客户端密码。

在这里插入图片描述

在这里插入图片描述

  • access_token:访问令牌,携带此令牌访问资源

  • token_type:有MAC Token与Bearer Token两种类型,两种的校验算法不同。

    RFC 6750建议Oauth2采用 Bearer Token(http://www.rfcreader.com/#rfc6750)。

  • refresh_token:刷新令牌,使用此令牌可以延长访问令牌的过期时间。

  • expires_in:过期时间,单位为秒。

  • scope:范围,与定义的客户端范围一致。

  • jti:当前token的唯一标识。


6.4 校验令牌

    Spring Security Oauth2提供校验令牌的端点,我们可以发送get请求携带令牌进行校验:

http://localhost:10000/oauth/check_token?token=68fb6574-6df2-4e0e-b419-78ca91b56a92

在这里插入图片描述


6.5 使用令牌访问资源

  • 不使用令牌对资源服务器进行访问,会返回401未认证;

    http://localhost:10001/cms/index
    

    在这里插入图片描述

  • 使用错误的令牌对资源服务器进行访问,会提示未认证、令牌无效;

    http://localhost:10001/cms/index?access_token=68fb6574-6df2-4e0e-b419-78ca91b56a91
    

    在这里插入图片描述

  • 使用令牌对资源服务器进行访问,能够正确访问。

    http://localhost:10001/cms/index?access_token=68fb6574-6df2-4e0e-b419-78ca91b56a92
    

    在这里插入图片描述



7. 简化模式

    简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此称简化模式,简化模式是相对于授权码模式而言的,简化模式相对不安全,因为浏览器(用户代理)持有token。 这里借了个图,简化模式工作流程如下图所示。

有些应用是纯前端应用,没有后台,就不能使用授权码模式了,必须将令牌存储在前端。简化模式允许直接向前端颁发令牌,这个模式没有请求授权码这个中间环节,所以称为(授权码)“隐藏式”(implicit)。简化模式不需要client_secret参数,所以不需要验证。

注意:OAuth2 授权码模式为什么不直接返回access_token?为什么简化模式又可以直接返回令牌?

在这里插入图片描述

7.1 授权服务器设置简化模式

在这里插入图片描述


7.2 申请令牌

    访问授权链接,在浏览器访问(Get请求)就可以,授权码模式response_type参数传token:

http://localhost:10000/oauth/authorize?client_id=cms&client_secret=secret&response_type=token

注意:参数含义参考6.2小节。

    如果没登录。那么自动会跳转至SpringSecurity的默认登录页面http://localhost:10000/login,具体代码是 http.formLogin().permitAll(); 。如果要弹窗登录的,可以配置 http.httpBasic(); ,但是这种配置是没有登录页面的。自定义登录页面可以这样配置http.formLogin().loginPage("/login").permitAll()

在这里插入图片描述

    输入用户密码(这里测试是用写死在授权服务器后台的用户信息)并登录。如果已经登录了,那么客户端会直接访问远程的授权服务器,申请令牌。

在这里插入图片描述

http://127.0.0.1:10001/cms/login#access_token=47dd0b77-f68d-43d3-92da-8a511aa0ea79&token_type=bearer&expires_in=1799&scope=all

    可以注意到,授权服务器重定向回我们指定的地址所携带的令牌参数放在了“hash fragment”部分。

注意:什么是hash fragment?就是URL当中#号后面的那一部分。 浏览器不会把URL当中的“hash fragment”发给服务器。hash fragment是只留在浏览器的地址栏的,它可以被网页的js读取到:window.location.hash。 既然hash fragment没有发给服务器,那即使黑客拦截到请求,也获取不到它。但是即便如此,由于浏览器是不安全的因素,所以相对授权码模式来说,简化模式仍相对不安全。


7.3 校验令牌

http://localhost:10000/oauth/check_token?token=47dd0b77-f68d-43d3-92da-8a511aa0ea79

在这里插入图片描述


7.4 使用令牌访问资源

  • 不使用令牌对资源服务器进行访问,会返回401未认证;

    http://localhost:10001/cms/index
    

    在这里插入图片描述

  • 使用错误的令牌对资源服务器进行访问,会提示令牌无效;

    http://localhost:10001/cms/index?access_token=47dd0b77-f68d-43d3-92da-8a511aa0ea78
    

    在这里插入图片描述

  • 使用令牌对资源服务器进行访问,能够正确访问。

    http://localhost:10001/cms/index?access_token=47dd0b77-f68d-43d3-92da-8a511aa0ea79
    

    在这里插入图片描述



8. 密码模式

    密码模式(resource owner password credentials):密码模式中,用户向客户端提供自己的用户名和密码,这通常用在用户对客户端高度信任的情况

再次借了个图,密码模式如图所示。

在这里插入图片描述

  • (A)用户访问客户端,提供URI连接包含用户名和密码信息给授权服务器;
  • (B)授权服务器对客户端进行身份验证;
  • (C)授权通过,返回acceptToken给客户端。

8.1 授权服务器设置密码模式

在这里插入图片描述

8.2 申请令牌

在这里插入图片描述

在这里插入图片描述

注意:参数含义、http basic认证参考6.3小节。

在这里插入图片描述


8.3 校验令牌

http://localhost:10000/oauth/check_token?token=bdf08566-7b04-4901-973d-cef41985e9a2

在这里插入图片描述


8.4 使用令牌访问资源

  • 不使用令牌对资源服务器进行访问,会返回401未认证;

    http://localhost:10001/cms/index
    

    在这里插入图片描述

  • 使用错误的令牌对资源服务器进行访问,会提示令牌无效;

    http://localhost:10001/cms/index?access_token=bdf08566-7b04-4901-973d-cef41985e9a1
    

    在这里插入图片描述

  • 使用令牌对资源服务器进行访问,能够正确访问。

    http://localhost:10001/cms/index?access_token=bdf08566-7b04-4901-973d-cef41985e9a2
    

    在这里插入图片描述



9. 客户端模式

    客户端模式(client credentials):客户端模式(client credentials)适用于没有前端的命令行应用,即在命令行下请求令牌。 这种模式和密码模式一样,同样使用于前后端分离的微服务架构中实现SSO。

注意:客户端模式是指客户端使用自己的名义而不是用户的名义向服务提供者申请授权,严格意义上客户端模式并不能算作 OAuth 协议要解决的问题的一种解决方案。

在这里插入图片描述

  • (A) 携带客户端的账户密码去获取token。
  • (B)拿到access_Token令牌之后,就可以直接访问资源。

9.1 授权服务器设置客户端模式

在这里插入图片描述


9.2 申请令牌

在这里插入图片描述

在这里插入图片描述


9.3 校验令牌

http://localhost:10000/oauth/check_token?token=2b033a83-1d91-409b-a841-8f57fb0cb351

在这里插入图片描述


9.4 使用令牌访问资源

  • 不使用令牌对资源服务器进行访问,会返回401未认证;

    http://localhost:10001/cms/index
    

    在这里插入图片描述

  • 使用错误的令牌对资源服务器进行访问,会提示令牌无效;

    http://localhost:10001/cms/index?access_token=2b033a83-1d91-409b-a841-8f57fb0cb350
    

    在这里插入图片描述

  • 使用令牌对资源服务器进行访问,能够正确访问。

    http://localhost:10001/cms/index?access_token=2b033a83-1d91-409b-a841-8f57fb0cb351
    

    在这里插入图片描述

10. 令牌存储方式

    对于token存储有如下方式,分别进行介绍:

  • InMemoryTokenStore:默认存储,保存在内存。
  • JdbcTokenStore:access_token存储在数据库。
  • JwtTokenStore:JWT这种方式比较特殊,这是一种无状态方式的存储,不进行内存、数据库存储,只是JWT中携带全面的用户信息,保存在jwt中携带过去校验就可以。
  • RedisTokenStore:将 access_token 存到 Redis 中。
  • JwkTokenStore:将 access_token 保存到 JSON Web Key。

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值