首页
/ Sa-Token OAuth2.0 实现

Sa-Token OAuth2.0 实现

2026-02-04 04:57:54作者:冯爽妲Honey

Sa-Token 提供了一套完整的 OAuth2.0 实现方案,支持多种授权模式(如授权码模式、密码模式、客户端模式等)。本文将详细介绍如何搭建 OAuth2-Server,并解析各授权模式的核心逻辑与使用方法。

OAuth2-Server 搭建

Sa-Token 的 OAuth2.0 实现提供了一套完整的 OAuth2-Server 搭建方案,支持多种授权模式(如授权码模式、密码模式、客户端模式等)。以下将详细介绍如何搭建一个 OAuth2-Server,并配置其核心功能。

1. 初始化 OAuth2-Server 配置

首先,需要在项目中初始化 SaOAuth2ServerConfig 配置类,设置 OAuth2-Server 的基本参数。以下是一个典型的配置示例:

@Configuration
public class SaOAuth2ServerConfig {

    @Bean
    public SaOAuth2ServerConfig getSaOAuth2ServerConfig() {
        SaOAuth2ServerConfig config = new SaOAuth2ServerConfig();

        // 启用授权码模式
        config.setEnableAuthorizationCode(true);

        // 设置令牌有效期(单位:秒)
        config.setAccessTokenTimeout(7200); // 2小时
        config.setRefreshTokenTimeout(2592000); // 30天

        // 添加客户端配置
        SaClientModel client = new SaClientModel()
                .setClientId("client1")
                .setClientSecret("123456")
                .setContractScopes(Arrays.asList("userinfo", "email"))
                .setAllowRedirectUris(Arrays.asList("http://localhost:8080/callback"));
        config.addClient(client);

        return config;
    }
}

2. 配置 OAuth2-Server 处理器

Sa-Token 提供了 SaOAuth2ServerProcessor 类,用于处理 OAuth2.0 的核心逻辑(如授权、令牌颁发等)。以下是一个简单的控制器示例:

@RestController
@RequestMapping("/oauth2")
public class SaOAuth2ServerController {

    @GetMapping("/authorize")
    public Object authorize(@RequestParam String response_type, @RequestParam String client_id, 
                           @RequestParam String redirect_uri, @RequestParam(required = false) String scope) {
        return SaOAuth2ServerProcessor.instance.authorize();
    }

    @PostMapping("/token")
    public Object token(@RequestParam String grant_type, @RequestParam(required = false) String code,
                        @RequestParam(required = false) String refresh_token) {
        return SaOAuth2ServerProcessor.instance.token();
    }
}

3. 支持的授权模式

Sa-Token 的 OAuth2-Server 支持以下授权模式:

授权模式 描述
授权码模式 适用于 Web 应用,通过授权码交换令牌。
密码模式 适用于信任的客户端,直接通过用户名和密码获取令牌。
客户端模式 适用于无用户参与的客户端,直接通过客户端凭证获取令牌。
刷新令牌模式 通过刷新令牌获取新的访问令牌。

4. 数据库存储配置

OAuth2-Server 需要存储令牌、授权码等数据。Sa-Token 提供了 SaOAuth2Dao 接口,支持自定义存储实现。以下是一个基于 Redis 的存储配置示例:

@Configuration
public class SaOAuth2DaoConfig {

    @Bean
    public SaOAuth2Dao getSaOAuth2Dao() {
        return new SaOAuth2Dao() {
            @Override
            public void saveCode(CodeModel code) {
                // 存储授权码逻辑
            }

            @Override
            public CodeModel getCode(String code) {
                // 获取授权码逻辑
                return null;
            }
        };
    }
}

5. 流程图:OAuth2-Server 授权流程

以下是一个典型的授权码模式流程图:

sequenceDiagram
    participant Client
    participant Server
    participant User

    Client->>Server: 发起授权请求
    Server->>User: 显示授权页面
    User->>Server: 确认授权
    Server->>Client: 返回授权码
    Client->>Server: 使用授权码请求令牌
    Server->>Client: 返回访问令牌和刷新令牌

6. 总结

通过以上步骤,可以快速搭建一个功能完善的 OAuth2-Server。Sa-Token 提供了灵活的配置选项和强大的扩展能力,能够满足各种场景的需求。在实际开发中,可以根据业务需求进一步定制化配置和存储逻辑。

授权码模式

授权码模式(Authorization Code Grant)是OAuth2.0中最常用的授权模式之一,适用于需要用户授权的场景。Sa-Token的OAuth2.0模块提供了完整的授权码模式实现,支持标准的OAuth2.0流程,包括授权码的生成、验证以及令牌的发放。

授权码模式流程

授权码模式的流程可以分为以下几个步骤:

  1. 用户授权请求:客户端将用户重定向到授权服务器,请求授权。
  2. 用户授权:用户在授权服务器上登录并授权。
  3. 授权码发放:授权服务器生成授权码并返回给客户端。
  4. 令牌请求:客户端使用授权码向授权服务器请求令牌。
  5. 令牌发放:授权服务器验证授权码后发放访问令牌和刷新令牌。

以下是一个典型的授权码模式流程图:

sequenceDiagram
    participant Client as 客户端
    participant User as 用户
    participant AuthServer as 授权服务器

    User->>Client: 访问客户端
    Client->>AuthServer: 重定向到授权页面
    User->>AuthServer: 登录并授权
    AuthServer->>Client: 返回授权码
    Client->>AuthServer: 使用授权码请求令牌
    AuthServer->>Client: 返回访问令牌和刷新令牌

核心类与功能

Sa-Token的授权码模式实现依赖于以下几个核心类:

  1. AuthorizationCodeGrantTypeHandler:处理授权码模式的令牌请求逻辑。
  2. SaOAuth2ServerConfig:配置授权码模式的启用状态及相关参数。
  3. SaOAuth2Template:提供授权码验证和令牌生成的模板方法。
  4. CodeModel:封装授权码的数据模型。

1. AuthorizationCodeGrantTypeHandler

AuthorizationCodeGrantTypeHandler是授权码模式的核心处理器,负责验证授权码并生成访问令牌。以下是其关键方法:

@Override
public AccessTokenModel getAccessToken(SaRequest req, String clientId, List<String> scopes) {
    // 验证授权码并生成令牌
    String code = req.getParam(Param.code);
    String redirectUri = req.getParam(Param.redirect_uri);
    CodeModel cm = SaOAuth2Manager.getTemplate().checkGainTokenParam(code, clientId, null, redirectUri);
    return SaOAuth2Manager.getDataGenerate().generateAccessToken(code);
}

2. SaOAuth2ServerConfig

SaOAuth2ServerConfig用于配置授权码模式的启用状态及相关参数。以下是关键配置项:

public class SaOAuth2ServerConfig {
    // 是否启用授权码模式
    private Boolean enableAuthorizationCode = true;
    // 授权码超时时间(毫秒)
    private long codeTimeout = 300000; // 5分钟
}

3. SaOAuth2Template

SaOAuth2Template提供了授权码验证的模板方法,确保授权码的有效性:

public CodeModel checkGainTokenParam(String code, String clientId, String clientSecret, String redirectUri) {
    CodeModel cm = getCode(code);
    SaOAuth2AuthorizationCodeException.throwBy(cm == null, "无效 code: " + code, code, SaOAuth2ErrorCode.CODE_30110);
    return cm;
}

4. CodeModel

CodeModel封装了授权码的数据模型,包含以下字段:

public class CodeModel {
    private String code; // 授权码
    private String clientId; // 客户端ID
    private Object loginId; // 用户ID
    private String redirectUri; // 重定向URI
    private List<String> scopes; // 授权范围
}

示例代码

以下是一个完整的授权码模式示例:

  1. 客户端发起授权请求
String authUrl = "http://auth-server/oauth2/authorize?response_type=code&client_id=client1&redirect_uri=http://client/callback";
response.sendRedirect(authUrl);
  1. 授权服务器生成授权码
CodeModel cm = new CodeModel()
    .setCode(UUID.randomUUID().toString())
    .setClientId("client1")
    .setLoginId("user1")
    .setRedirectUri("http://client/callback");
SaOAuth2Manager.getDao().saveCode(cm);
  1. 客户端使用授权码请求令牌
String tokenUrl = "http://auth-server/oauth2/token?grant_type=authorization_code&code=xxx&redirect_uri=http://client/callback";
AccessTokenModel token = SaOAuth2Manager.getTemplate().token(tokenUrl);

总结

授权码模式是OAuth2.0中最安全的授权方式之一,适用于需要用户交互的场景。Sa-Token通过AuthorizationCodeGrantTypeHandlerSaOAuth2ServerConfig等核心类提供了完整的实现,开发者可以轻松集成到自己的项目中。

Sa-Token OAuth2.0 实现:密码模式详解

OAuth2.0 的密码模式(Password Grant Type)是一种直接通过用户名和密码获取访问令牌的方式,适用于高度信任的场景。Sa-Token 提供了完整的密码模式实现,本文将深入解析其核心逻辑、使用方法和注意事项。

密码模式的核心逻辑

密码模式的流程如下:

  1. 客户端请求:客户端将用户名和密码直接发送到授权服务器。
  2. 服务器验证:授权服务器验证用户名和密码的有效性。
  3. 令牌发放:验证通过后,服务器返回访问令牌(Access Token)和可选的刷新令牌(Refresh Token)。

以下是 Sa-Token 中密码模式的核心代码实现:

public class PasswordGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterface {
    @Override
    public String getHandlerGrantType() {
        return GrantType.password;
    }

    @Override
    public AccessTokenModel getAccessToken(SaRequest req, String clientId, List<String> scopes) {
        String username = req.getParamNotNull(SaOAuth2Consts.Param.username);
        String password = req.getParamNotNull(SaOAuth2Consts.Param.password);
        PasswordAuthResult passwordAuthResult = loginByUsernamePassword(username, password);
        Object loginId = passwordAuthResult.getLoginId();
        RequestAuthModel ra = new RequestAuthModel(clientId, scopes, loginId);
        return SaOAuth2Manager.getDataGenerate().generateAccessToken(ra, true, atm -> atm.grantType = GrantType.password);
    }

    public PasswordAuthResult loginByUsernamePassword(String username, String password) {
        System.err.println("警告信息:当前 password 认证模式,使用默认实现 (SaOAuth2Strategy.instance.doLoginHandle),仅供开发测试");
        return SaOAuth2Strategy.instance.doLoginHandle.apply(username, password);
    }
}

使用方法

1. 启用密码模式

在 Sa-Token 的 OAuth2.0 配置中,需显式启用密码模式:

SaOAuth2ServerConfig config = new SaOAuth2ServerConfig();
config.setEnablePassword(true);

2. 自定义登录逻辑

默认的 loginByUsernamePassword 方法仅用于测试,实际项目中需重写此方法以实现自定义的用户名密码验证逻辑:

public class CustomPasswordGrantTypeHandler extends PasswordGrantTypeHandler {
    @Override
    public PasswordAuthResult loginByUsernamePassword(String username, String password) {
        if ("sa".equals(username) && "123456".equals(password)) {
            return new PasswordAuthResult().setLoginId("10001");
        }
        throw new SaOAuth2Exception("用户名或密码错误");
    }
}

3. 注册自定义处理器

将自定义处理器注册到 Sa-Token 的策略中:

SaOAuth2Strategy.instance.registerGrantTypeHandler(new CustomPasswordGrantTypeHandler());

注意事项

  1. 安全性:密码模式直接将用户凭证暴露给客户端,仅适用于高度信任的场景(如第一方应用)。
  2. 令牌有效期:建议设置较短的访问令牌有效期,并通过刷新令牌续期。
  3. 日志记录:记录所有密码模式的请求,便于审计和异常排查。

示例流程图

sequenceDiagram
    participant Client
    participant Server
    Client->>Server: POST /token (grant_type=password&username=sa&password=123456)
    Server->>Server: 验证用户名和密码
    alt 验证成功
        Server-->>Client: 返回 Access Token 和 Refresh Token
    else 验证失败
        Server-->>Client: 返回错误信息
    end

通过以上内容,您可以快速掌握 Sa-Token 中密码模式的实现与使用方法。

客户端凭证模式

OAuth2.0 的客户端凭证模式(Client Credentials Grant)是一种适用于机器对机器(M2M)通信的授权模式。它允许客户端直接使用自己的凭证(Client ID 和 Client Secret)获取访问令牌,而无需用户参与。这种模式适用于后台服务之间的通信,例如微服务之间的调用。

核心流程

客户端凭证模式的流程如下:

sequenceDiagram
    participant Client as 客户端
    participant AuthServer as 授权服务器

    Client->>AuthServer: 1. 请求令牌 (Client ID + Client Secret + grant_type=client_credentials)
    AuthServer-->>Client: 2. 返回访问令牌 (Access Token)
  1. 客户端请求令牌:客户端向授权服务器发送请求,携带 client_idclient_secretgrant_type=client_credentials
  2. 授权服务器验证:授权服务器验证客户端的凭证,并生成访问令牌。
  3. 返回令牌:授权服务器将访问令牌返回给客户端。

代码实现

在 Sa-Token 中,客户端凭证模式的实现主要涉及以下几个核心类:

  1. GrantType:定义了 client_credentials 作为授权类型。
  2. SaOAuth2ServerProcessor:处理客户端凭证模式的令牌请求。
  3. SaClientModel:存储客户端的配置信息,包括允许的授权类型。

示例代码

以下是一个客户端凭证模式的请求示例:

// 客户端请求令牌
String tokenUrl = "http://auth-server.com/oauth2/token";
Map<String, String> params = new HashMap<>();
params.put("client_id", "your_client_id");
params.put("client_secret", "your_client_secret");
params.put("grant_type", "client_credentials");

// 发送请求
String response = HttpUtil.post(tokenUrl, params);
System.out.println("Access Token: " + response);

服务端配置

在 Sa-Token 中,可以通过 SaOAuth2ServerConfig 配置是否启用客户端凭证模式:

@Configuration
public class SaOAuth2Config {
    @Bean
    public SaOAuth2ServerConfig saOAuth2ServerConfig() {
        return new SaOAuth2ServerConfig()
                .setEnableClientCredentials(true) // 启用客户端凭证模式
                .addClient(new SaClientModel()
                        .setClientId("your_client_id")
                        .setClientSecret("your_client_secret")
                        .addAllowGrantTypes("client_credentials")); // 允许客户端凭证模式
    }
}

适用场景

客户端凭证模式适用于以下场景:

  • 后台服务调用:微服务之间的 API 调用。
  • 自动化任务:定时任务或批处理作业。
  • 无用户交互:不需要用户参与的机器对机器通信。

注意事项

  1. 安全性:客户端凭证模式依赖于 client_secret,必须确保其安全性,避免泄露。
  2. 权限控制:客户端获取的访问令牌通常具有较高的权限,需严格控制其访问范围。
  3. 刷新令牌:客户端凭证模式不支持刷新令牌,访问令牌过期后需重新获取。

通过 Sa-Token 的 OAuth2.0 实现,可以轻松集成客户端凭证模式,满足后台服务的安全通信需求。

Sa-Token 的 OAuth2.0 实现提供了灵活且安全的授权方案,适用于各种场景。通过本文的介绍,您可以快速掌握如何搭建 OAuth2-Server 并集成不同的授权模式。无论是 Web 应用、微服务还是自动化任务,Sa-Token 都能满足您的需求。

登录后查看全文
热门项目推荐
相关项目推荐