Spring Security OAuth2学习记录(一)

一、OAuth2.0 1、概念 OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的 规范标准 。与以往的授权方式不同之处是 OAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就 可以申请获得该用户资源的授权,因此 OAuth 是开放的安全的。 2、应用场景 (1)第三方应用授权登陆:例如用微信登陆其他平台 (2)原生App授权:app请求后台接口都需要携带 Token信息 (3)前后端分离框架,前端请求后台数据,需要进行oauth2安全认证 3、oauth2.0 角色: (1) 资源所有者(Resource Owner):通常为用户,例如“张三”想通过微信扫码登陆微博,微博需要张三微信的头像、昵称,那么“张三”既为资源所有者。 (2) 第三方应用(Third-party Application):又称为客户端(client),例如微博想要获取张三的微信头像、昵称等信息,此时微博对于微信认证服务器来说就是客户端。 (3) 认证服务器 ( Authorization Server):对资源所有者进行身份认证;对要访问资源的客户端进行授权、产生令牌。 (4) 资源服务器(Resource Server):存储用户资源,例如微信存储了用户的头像、昵称;验证令牌的有效性。 (5) 服务提供商(Service Provider):例如微信,(包含认证服务器和资源服务器) 4、抽象流程 Spring Security OAuth2学习记录(一) 流程分析: (1)客户端发送认证请求(微博,获取张三的微信头像、昵称) (2)资源拥有者(张三)同意授权 (3)客户端向认证服务器获取授权码、Token(微信) (4)认证服务器返回Token (5)客户端携带Token去获取被保护的资源 (6)资源服务器返回被保护的资源 5、Oauth2.0的4种模式(具体结合代码讲述) (1)授权码模式 (2)简化模式 (3)密码模式 (4)客户端模式 二、Spring Security 实现Oauth2.0

1、创建Maven项目

(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.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.cmxy</groupId>
    <artifactId>oauth2-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>oauth2-demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

        <!-- Spring Security、OAuth2 和JWT相关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

        <!--Web相关-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--Mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>

        <!--Mysql连接驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

(2)项目结构

Spring Security OAuth2学习记录(一)

2、代码实现(暂时只是最简单的实现,后面会不断补充)

(1)创建认证服务器配置类

package com.cmxy.oauth2.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.stereotype.Component;

/**
 * 认证服务器配置类
 * 作用:配置哪些客户端可以访问当前配置服务器
 */
@Component
@EnableAuthorizationServer //标记为认证服务器
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    /**
     * 配置可以访问此认证服务器的客户端信息
     * 可以采用:JDBC或者内存的方式(原理其实差不太多)
     * 为了方便暂时使用基于内存的形式存储客户端信息
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()//基于内存的模式
                .withClient("client")//客户端ID
                .secret(passwordEncoder.encode("123456"))//客户端秘钥,这里一定要加密。SpringSecurity 5.0之后规定密码必须加密。
                .resourceIds("product")//能访问的资源ID
                .scopes("user")//能访问的范围
                //授权方式:即当前认证服务器支持的授权方式分贝为 授权码模式、密码模式、客户端模式、简易模式、刷新Token
                .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
                .autoApprove(false)//是否自动授权,一般设置为false表示需要用户手动授权
                .redirectUris("www.baidu.com");//重定向路径
    }

}

(2)创建Spring Security配置类

package com.cmxy.oauth2.server.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password(passwordEncoder.encode("1234"))
                .authorities("product");
    }
}

(3)配置加密方式(SpringSecurity5.0之后,要求必须密码加密)

package com.cmxy.oauth2.server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SpringSecurityBean {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

3、接口测试

首先测试的是授权码模式

授权码模式:

功能最完整,流程最严密的授权模式。国内各大服务提供商(微信、QQ、微 博、淘宝 、百度)都采用此模式进行授权。可以确定是用户真正同意授权;而且令牌是认证服务器发放给第三方应 用的服务器,而不是浏览器上。

(1)在浏览器输入url:http://localhost:8080/oauth/authorize?client_id=client&response_type=code

其中:client_id 为配置类中配置的,响应的类型为授权码

(2)此时因为之前未登录所以会跳转到登陆页

Spring Security OAuth2学习记录(一)

注意这里的账号密码是资源拥有者的,不是客户端的!!!在本demo中,账号为admin 密码123456

登陆成功后跳转到授权页面(是不是有点类似于微信的授权)

Spring Security OAuth2学习记录(一)

 (3)选择授权,则会跳转到之前配置的重定向路径,也就是百度

Spring Security OAuth2学习记录(一)

 

 注意此时是包含了授权码,最后拿授权码去换token,每个授权码只能使用一次。

(4)获取Token

Spring Security OAuth2学习记录(一)

 Spring Security OAuth2学习记录(一)

Spring Security OAuth2学习记录(一) 

 最后则携带Token去请求对应资源。至此最复杂的授权码模式已经完成

未完待续。。。

上一篇:01->SpringSecurity认证框架的自定义配置(微服务第一步)


下一篇:JS/Jquery遍历JSON对象、JSON数组、JSON数组字符串、JSON对象字符串