Java SpringBoot 自研应用接入 SSO 示例

本篇文档以 Java SpringBoot 为例,讲解作为自研应用与 IDaaS 的对接。

若您希望了解对接原理和调用流程,请参考自研应用接入 SSO

IDaaS 自研应用采用 OIDC 授权码模式,该模式向下兼容 OAuth 2.0 协议授权码模式,所以可以采用 OAuth 工具包spring-boot-starter-oauth2-client完成对接开发。

该工具包封装了所有的 OIDC 授权码模式调用流程和 id_token 解析过程,使用起来非常简单。

1. 引入工具包

pom.xml中增加依赖:spring-boot-starter-oauth2-client,示例如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.1</version>
</parent>

<properties>
    <java.version>8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>
</dependencies>

2. 配置 IDaaS 信息

client_id,client_secretissuerapplication.properties中配置:

spring.security.oauth2.client.registration.aliyunidaas.client-id=app_***
spring.security.oauth2.client.registration.aliyunidaas.client-secret=CS***
spring.security.oauth2.client.provider.aliyunidaas.issuer-uri=<issuer>

上述信息,均可在应用创建后获取,请参考自研应用接入 SSO

3. 配置 Security 需要 OAuth 认证

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;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2Login();
    }
}

4. 获取 User 信息

工具包为自动完成所有的授权调用和 id_token 验证机制。

通过注入@AuthenticationPrincipal OAuth2User user即可获得最终的用户信息:

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SampleController {

    @GetMapping("/user")
    public OAuth2User user(@AuthenticationPrincipal OAuth2User user) {
        return user;
    }
}

最后可尝试在 /user 端点输出用户信息:

使用这些用户信息,直接将用户登录,即可完成 SSO 过程。

若应用部署在代理之后

如果将应用部署在代理后面,比如阿里云SLB、Nginx等,在测试时可能会发现如下情况下:

  • 用户访问 https://www.example.com

  • OIDC登录跳转时产生的 redirect_uri 变成了 http://127.0.0.1:8080/oauth2/authorization/aliyunidaas 这样的形式,会导致登录不了。

如果需要解决这个问题,就需要修改 SpringBoot 生成 redirect_uri 的逻辑,具体方法是:

  1. 在 SpringBoot 中配置增加配置项

server.forward-headers-strategy = NATIVE
  1. 如果用户有使用阿里云SLB则需要在SLB高级配置中勾选“通过 X-Forwarded-Proto 头字段获取 SLB 的监听协议”,如下图所示:

image

  1. 如果用户在SLB与应用之间有Nginx代理,则需要在代理上配置:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;

  1. 如果用户直接通过NginxHTTPS方式提供服务,则需要配置:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;

如果您使用了他们代理类服务或软件,需要自行查找配置,最终需要确保SpringBoot收到的请求中传入了正确的 HostX-forwarded-Proto 这两个HTTP Header。

相关参考资料:

https://tools.ietf.org/html/rfc7239

https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/

https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.webserver.use-behind-a-proxy-server