Skip to content

Commit b123d15

Browse files
committed
新增事件回调以及通过Developer API全量拉取用户及组织
1 parent 5f721c7 commit b123d15

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2525
-270
lines changed

README.md

+86-1
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,89 @@ idaas:
7171
### 可以通过SP发起登录,也可以通过IdP发起登录
7272
PKCE可以防止攻击者窃取code,从而通过code去拿到令牌。主要流程如下:
7373
![img_14.png](src/main/resources/static/img/img_14.png)
74-
SP登录与IdP发起的登录可参考授权码流。
74+
SP登录与IdP发起的登录可参考授权码流。
75+
76+
# 用户/组织全量拉取
77+
## 1. developer API依赖
78+
```pom
79+
<dependency>
80+
<groupId>com.aliyun</groupId>
81+
<artifactId>alibabacloud-eiam_developerapi20220225</artifactId>
82+
<version><请替换成最新版本></version>
83+
</dependency>
84+
```
85+
## 2. 相关配置
86+
(1)全量拉取需要配置拉取的实例和应用以及需要拉取的范围,这里默认拉取IDaaS根节点下的所有用户和组织。实例ID和应用ID需要配置在配置项中。
87+
```yaml
88+
idaas:
89+
instance-id: # 实例ID
90+
application-id: # 应用ID
91+
```
92+
(2)需要在IDaaS相应的应用打开API开放的接口以及相应的接口权限。如下图所示。
93+
![img.png](src/main/resources/static/img/img_16.png)
94+
## 3. 接口调用
95+
```http request
96+
POST http://127.0.0.1:8082/trigger_sync
97+
```
98+
Demo中采用H2内存数据库进行数据的存储,数据库表为user_info,ou_info,表结构如下所示:
99+
```sql
100+
create table user_info (
101+
user_id varchar(255) not null,
102+
external_id varchar(255),
103+
external_ou_id varchar(255),
104+
ou_id varchar(255),
105+
phone_number varchar(255),
106+
phone_region varchar(255),
107+
user_email varchar(255),
108+
username varchar(255),
109+
primary key (user_id)
110+
)
111+
create index external_id_index on user_info (external_id)
112+
113+
create table ou_info (
114+
ou_id varchar(255) not null,
115+
ou_external_id varchar(255),
116+
ou_name varchar(255),
117+
parent_ou_id varchar(255),
118+
primary key (ou_id)
119+
)
120+
create index ou_external_id_index on ou_info (ou_external_id)
121+
```
122+
备注:
123+
(1)避免在同步过程中移动组织、用户。以免目录结构出错, Demo中将external_id和ou_external_id,设置唯一索引,若发现同步过程中组织重复,则抛错回滚。
124+
(2)运行应用时该数据库若不存在则会进行新建,路径为./temp/data
125+
126+
其中IDaaS与Demo中的字段映射如下所示,可以根据业务需求自行修改:
127+
128+
| Demo字段 | user_id | user_name | phone_region| phone_number | user_email | external_id | external_ou_id |
129+
|---------|--------------|------------------------|----------------------------|---------------|------------|--------------|------------------------|
130+
| IDaaS字段 | external_id | user_name|phone_region| phone_number | email | user_id | organizational_unit_id |
131+
132+
133+
134+
| Demo字段 | ou_id | ou_external_id | ou_name | parent_ou_id |
135+
|---------|---------------------------------|------------------------|--------------------------|--------------|
136+
| IDaaS字段 | organizational_unit_external_id | organizational_unit_id| organizational_unit_name | parent_id |
137+
138+
# IDaaS账户/组织同步到Demo应用
139+
## 1. 相关配置信息
140+
```yaml
141+
idaas:
142+
syncConfig:
143+
enabled: true #同步到账户开关是否开启
144+
callback-uri: ${custom.server-domain}/receive_sync #同步回调接收地址
145+
encrypt-required: true #是否加密传输
146+
encrypt-key: #IDaaS应用中对应的加密密钥
147+
jwks-uri: #IDaaS应用中账户同步中对应的验签公钥端点
148+
149+
```
150+
(1) 在IDaaS中注册的应用需要打开IDaaS同步到应用的开关
151+
![img_1.png](src/main/resources/static/img/img_17.png)
152+
(2) 在IDaaS中设置同步范围,业务是否解密等信息,同时设置同步接收地址为当前demo中的${custom.server-domain}/receive_sync,即http://127.0.0.1:8082/receive_sync
153+
![img_2.png](src/main/resources/static/img/img_18.png)
154+
(3) 在IDaaS中设置回调事件以及全量推送范围
155+
![img_3.png](src/main/resources/static/img/img_19.png)
156+
## 2.接口调用
157+
```http request
158+
POST http://127.0.0.1:8082/receive_sync?event=<your event>
159+
```

pom.xml

+34-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<dependency>
2525
<groupId>com.alibaba</groupId>
2626
<artifactId>fastjson</artifactId>
27-
<version>1.2.75_noneautotype</version>
27+
<version>2.0.12</version>
2828
</dependency>
2929
<dependency>
3030
<groupId>org.springframework.boot</groupId>
@@ -57,7 +57,7 @@
5757
<dependency>
5858
<groupId>com.google.guava</groupId>
5959
<artifactId>guava</artifactId>
60-
<version>20.0</version>
60+
<version>31.1-jre</version>
6161
</dependency>
6262
<dependency>
6363
<groupId>org.springframework.boot</groupId>
@@ -69,6 +69,38 @@
6969
<artifactId>jose4j</artifactId>
7070
<version>0.7.9</version>
7171
</dependency>
72+
<!--developer API-->
73+
<dependency>
74+
<groupId>com.aliyun</groupId>
75+
<artifactId>alibabacloud-eiam_developerapi20220225</artifactId>
76+
<version>1.0.3</version>
77+
</dependency>
78+
79+
80+
<dependency>
81+
<groupId>org.springframework.boot</groupId>
82+
<artifactId>spring-boot-starter-data-jpa</artifactId>
83+
<version>2.6.3</version>
84+
</dependency>
85+
<!--H2数据库-->
86+
<dependency>
87+
<groupId>com.h2database</groupId>
88+
<artifactId>h2</artifactId>
89+
<version>1.4.200</version>
90+
</dependency>
91+
92+
<dependency>
93+
<groupId>com.aliyunidaas</groupId>
94+
<artifactId>idaas-sync</artifactId>
95+
<version>1.1.0</version>
96+
</dependency>
97+
98+
<dependency>
99+
<groupId>junit</groupId>
100+
<artifactId>junit</artifactId>
101+
<scope>test</scope>
102+
</dependency>
103+
72104
</dependencies>
73105

74106
<build>

src/main/java/com/aliyunidaas/sample/common/EndpointContext.java

+12-12
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,30 @@ public String getAuthorizationEndpoint() {
2424
return authorizationEndpoint;
2525
}
2626

27-
public void setAuthorizationEndpoint(String authorizationEndpoint) {
28-
this.authorizationEndpoint = authorizationEndpoint;
29-
}
30-
3127
public String getTokenEndpoint() {
3228
return tokenEndpoint;
3329
}
3430

35-
public void setTokenEndpoint(String tokenEndpoint) {
36-
this.tokenEndpoint = tokenEndpoint;
37-
}
38-
3931
public String getUserinfoEndpoint() {
4032
return userinfoEndpoint;
4133
}
4234

43-
public void setUserinfoEndpoint(String userinfoEndpoint) {
44-
this.userinfoEndpoint = userinfoEndpoint;
45-
}
46-
4735
public String getJwksUri() {
4836
return jwksUri;
4937
}
5038

39+
public void setAuthorizationEndpoint(String authorizationEndpoint) {
40+
this.authorizationEndpoint = authorizationEndpoint;
41+
}
42+
43+
public void setTokenEndpoint(String tokenEndpoint) {
44+
this.tokenEndpoint = tokenEndpoint;
45+
}
46+
47+
public void setUserinfoEndpoint(String userinfoEndpoint) {
48+
this.userinfoEndpoint = userinfoEndpoint;
49+
}
50+
5151
public void setJwksUri(String jwksUri) {
5252
this.jwksUri = jwksUri;
5353
}

src/main/java/com/aliyunidaas/sample/common/SimpleAuthnInterceptor.java

+22-23
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package com.aliyunidaas.sample.common;
22

33
import com.aliyunidaas.sample.common.cache.CacheManager;
4-
import com.aliyunidaas.sample.common.config.CustomOidcConfiguration;
4+
import com.aliyunidaas.sample.common.config.InitConfiguration;
55
import com.aliyunidaas.sample.common.factory.CodeChallengeMethodFactory;
6-
import com.aliyunidaas.sample.common.factory.ParameterNameFactory;
6+
import com.aliyunidaas.sample.common.factory.ConstantParams;
77
import com.aliyunidaas.sample.common.util.CommonUtil;
88
import org.apache.commons.lang.StringUtils;
99
import org.springframework.beans.factory.annotation.Autowired;
@@ -41,25 +41,25 @@ public class SimpleAuthnInterceptor implements HandlerInterceptor {
4141
private final static String UTF_8 = "UTF-8";
4242

4343
@Autowired
44-
private CustomOidcConfiguration customOidcConfiguration;
44+
private InitConfiguration initConfiguration;
4545

4646
@Autowired
4747
private CacheManager cacheManager;
4848

4949
@Override
5050
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
5151
throws IOException, NoSuchAlgorithmException, IllegalAccessException {
52-
Cookie cookie = WebUtils.getCookie(request, ParameterNameFactory.COOKIE_NAME);
52+
Cookie cookie = WebUtils.getCookie(request, ConstantParams.COOKIE_NAME);
5353
if (cookie == null) {
5454
String state = UUID.randomUUID().toString();
55-
String redirectUri = customOidcConfiguration.getRedirectUri();
56-
String iDaaSLoginUri = getIDaaSLoginUri(request, state, redirectUri);
57-
if (customOidcConfiguration.isPkceRequired()) {
58-
iDaaSLoginUri = getIDaaSLoginUri(state, iDaaSLoginUri);
55+
String redirectUri = initConfiguration.getOidcConfig().getRedirectUri();
56+
String eiamLoginUri = getEiamLoginUri(request, state, redirectUri);
57+
if (initConfiguration.getOidcConfig().isPkceRequired()) {
58+
eiamLoginUri = getEiamLoginUri(state, eiamLoginUri);
5959
}
60-
response.sendRedirect(iDaaSLoginUri);
60+
response.sendRedirect(eiamLoginUri);
6161
} else {
62-
String cookieValue = cacheManager.getCache(CommonUtil.generateCacheKey(cookie.getValue(), ParameterNameFactory.COOKIE_NAME));
62+
String cookieValue = cacheManager.getCache(CommonUtil.generateCacheKey(cookie.getValue(), ConstantParams.COOKIE_NAME));
6363
if (StringUtils.isBlank(cookieValue) || !cookie.getValue().equals(cookieValue)) {
6464
throw new IllegalAccessException(ILLEGAL_ACCESS_EXCEPTION_MESSAGE);
6565
}
@@ -74,47 +74,46 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
7474
* @param state 用于作为缓存的key以及作为随机值用于跨站保护
7575
* @return 登录的重定向地址
7676
*/
77-
private String getIDaaSLoginUri(HttpServletRequest request, String state, String redirectUri)
77+
private String getEiamLoginUri(HttpServletRequest request, String state, String redirectUri)
7878
throws MalformedURLException, UnsupportedEncodingException {
79-
EndpointContext endpointContext = cacheManager.getCache(customOidcConfiguration.getIssuer());
79+
EndpointContext endpointContext = cacheManager.getCache(initConfiguration.getOidcConfig().getIssuer());
8080
String authorizationEndpoint = endpointContext.getAuthorizationEndpoint();
81-
final String clientId = customOidcConfiguration.getClientId();
82-
final String scopes = customOidcConfiguration.getScopes().replace(" ", "%20");
81+
final String clientId = initConfiguration.getOidcConfig().getClientId();
8382

8483
final String queryString = request.getQueryString();
8584
final String requestUrl = request.getRequestURL().toString();
8685
final URL url = new URL(requestUrl);
8786
String callbackUrl = url.getPath() + (queryString == null ? "" : "?" + queryString);
88-
cacheManager.setCache(CommonUtil.generateCacheKey(state, ParameterNameFactory.URI), callbackUrl);
87+
cacheManager.setCache(CommonUtil.generateCacheKey(state, ConstantParams.URI), callbackUrl);
8988
// responseType = code , It means that this is an authorization code request
9089
return authorizationEndpoint +
9190
"?response_type=code"
9291
+ "&client_id=" + URLEncoder.encode(clientId, UTF_8)
9392
+ "&redirect_uri=" + URLEncoder.encode(redirectUri, UTF_8)
94-
+ "&scope=" + URLEncoder.encode(scopes, UTF_8)
93+
+ "&scope=" + URLEncoder.encode(initConfiguration.getOidcConfig().getScopes(), UTF_8).replace("+","%20")
9594
+ "&state=" + URLEncoder.encode(state, UTF_8);
9695
}
9796

9897
/**
9998
* Obtain the redirection URL of Authorization Code With PKCE Flow
10099
*
101100
* @param state 缓存code verifier 的key
102-
* @param iDaaSLoginUri 授权码情况下的重定向地址
101+
* @param eiamLoginUri 授权码情况下的重定向地址
103102
* @return pkce情况下登录的的重定向地址
104103
* @throws NoSuchAlgorithmException
105104
*/
106-
private String getIDaaSLoginUri(String state, String iDaaSLoginUri) throws NoSuchAlgorithmException, UnsupportedEncodingException {
105+
private String getEiamLoginUri(String state, String eiamLoginUri) throws NoSuchAlgorithmException, UnsupportedEncodingException {
107106
String codeVerifier = createCodeVerifier();
108107
String codeChallenge = codeVerifier;
109-
String codeChallengeMethod = customOidcConfiguration.getCodeChallengeMethod();
108+
String codeChallengeMethod = initConfiguration.getOidcConfig().getCodeChallengeMethod();
110109
if (codeChallengeMethod.equals(CodeChallengeMethodFactory.SHA_256)) {
111110
codeChallenge = createHash(codeVerifier);
112111
}
113-
cacheManager.setCache(CommonUtil.generateCacheKey(state, ParameterNameFactory.CODE_VERIFIER), codeVerifier);
114-
iDaaSLoginUri = iDaaSLoginUri
115-
+ "&code_challenge_method=" + URLEncoder.encode(customOidcConfiguration.getCodeChallengeMethod(), UTF_8)
112+
cacheManager.setCache(CommonUtil.generateCacheKey(state, ConstantParams.CODE_VERIFIER), codeVerifier);
113+
eiamLoginUri = eiamLoginUri
114+
+ "&code_challenge_method=" + URLEncoder.encode(initConfiguration.getOidcConfig().getCodeChallengeMethod(), UTF_8)
116115
+ "&code_challenge=" + URLEncoder.encode(codeChallenge, UTF_8);
117-
return iDaaSLoginUri;
116+
return eiamLoginUri;
118117
}
119118

120119
/**

src/main/java/com/aliyunidaas/sample/common/cache/LocalCacheManager.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ public class LocalCacheManager implements CacheManager {
1818

1919
private final Cache<String, Object> cache = CacheBuilder
2020
.newBuilder()
21-
//设置cache的初始大小
21+
// 设置cache的初始大小
2222
.initialCapacity(20)
23-
//并发数
23+
// 并发数
2424
.concurrencyLevel(2)
25-
//过期时间
25+
// 过期时间
2626
.expireAfterWrite(3600, TimeUnit.SECONDS)
2727
.build();
2828

0 commit comments

Comments
 (0)