一、概述
在企业内部环境中,若已构建一套完备的单点登录系统(SSO),基于提升企业信息化管理效率与用户体验的考量,往往会要求将所有内部系统接入该 SSO 体系。本文着重阐释运用 Oinone 进行开发的项目,与 SSO 系统实现对接的具体实施方法与步骤。
二、对接步骤
1、项目自定义实现UserCookieLogin,可参考示例说明:pro.shushi.pamirs.user.api.login.UserCookieLoginFree
2、对接SSO示例
java
package pro.shushi.pamirs.demo.core.sso;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import pro.shushi.pamirs.demo.core.sso.constant.HttpConstant;
import pro.shushi.pamirs.demo.core.sso.constant.SessionUserTypeEnum;
import pro.shushi.pamirs.demo.core.sso.model.ApiCommonTransient;
import pro.shushi.pamirs.demo.core.sso.model.PermissionInfoResp;
import pro.shushi.pamirs.demo.core.sso.utils.AuthenticateUtils;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.dto.model.PamirsUserDTO;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.meta.common.exception.PamirsException;
import pro.shushi.pamirs.meta.common.spring.BeanDefinitionUtils;
import pro.shushi.pamirs.resource.api.enmu.UserSignUpType;
import pro.shushi.pamirs.user.api.cache.UserCache;
import pro.shushi.pamirs.user.api.constants.UserConstant;
import pro.shushi.pamirs.user.api.enmu.UserExpEnumerate;
import pro.shushi.pamirs.user.api.enmu.UserLoginTypeEnum;
import pro.shushi.pamirs.user.api.login.IUserLoginChecker;
import pro.shushi.pamirs.user.api.login.UserCookieLogin;
import pro.shushi.pamirs.user.api.login.UserCookieLoginSimple;
import pro.shushi.pamirs.user.api.model.PamirsUser;
import pro.shushi.pamirs.user.api.model.tmodel.PamirsUserTransient;
import pro.shushi.pamirs.user.api.service.UserService;
import pro.shushi.pamirs.user.api.utils.CookieUtil;
import javax.servlet.http.HttpServletResponse;
/**
*
* @author shushi
*
* 完全自定义login的过程
* 需要实现登陆部分login 以及拦截部分fetchUserIdByReq
* 如果fetchUserIdByReq返回值为null的时候 将会被拦截
*/
@Slf4j
@Order(0)
@Component
public class DemoUserSSOCookieLogin extends UserCookieLogin<PamirsUser> {
//刷新令牌
private static String REFRESH_TOKEN = "refreshToken";
//系统id
private static String CLIENT_ID = "client-id";
//访问令牌
private static String AUTHORIZATION = "Authorization";
private IUserLoginChecker checker;
@Autowired
private UserService userService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public String type() {
return UserLoginTypeEnum.COOKIE.value();
}
@Override
public PamirsUser resolveAndVerification(PamirsUserTransient user) {
if (checker == null) {
checker = BeanDefinitionUtils.getBean(IUserLoginChecker.class);
}
return checker.check4login(user);
}
/**
* 重写登录拦截功能
* 该函数主要作用,通过三方权限校验.
* @return
*/
// 版本升级需要修改
@Override
public PamirsUserDTO fetchUserIdByReq() {
String sessionId = PamirsSession.getSessionId();
PamirsUserDTO pamirsUserDTO = UserCache.get(sessionId);
if (pamirsUserDTO ==null) {
//H5-企业微信登录,其他SSO登录。获取标识
String accessToken = (String) PamirsSession.getRequestVariables().getVariables().get("accessToken");
ApiCommonTransient permissionInfo = AuthenticateUtils.getPermissionInfo(accessToken);
// *******登录成功的条件判断,各SSO根据情况自行修改********
if(HttpConstant.SUCCESS.equals(permissionInfo.getCode())) {
// SSO用户 换 Oinone用户
PamirsUser pamirsUser = setUserInfoToCookiesAndSetUserIdToCache(permissionInfo,accessToken);
return new PamirsUserDTO().setUserId(pamirsUser.getId()).setPhone(pamirsUser.getPhone())
.setUserCode(pamirsUser.getCode()).setLogin(pamirsUser.getLogin()).setEmail(pamirsUser.getEmail()).setUserName(pamirsUser.getName());
} else {
//用户未登录,并且token未获取到用户null(根据实际情况修改)
return null;
}
} else {
return fetchUserIdByReq4Pamirs();
}
}
/**
* 开放一个用户登录setCookies函数 供登录和跳转校验
* @param permissionInfo
* @param accessToken
* @return
*/
public PamirsUser setUserInfoToCookiesAndSetUserIdToCache(ApiCommonTransient permissionInfo, String accessToken) {
PermissionInfoResp ssoResponseTransient = JSON.parseObject(permissionInfo.getData().toString(), PermissionInfoResp.class);
// *********示例:SSO跟业务系统中用户ID关联;其他关联条件请根据数据情况处理*******
PamirsUser pamirsUser = userService.queryById(ssoResponseTransient.getUserInfo().getId());
if (pamirsUser == null) {
// ********SSO中有用户数据,Oinone的系统中没有需要怎么处理************/
// ********这里仅仅是一个示例,在上述情况下创建用户,请根据实际情况处理,请根据实际情况处理*****/
pamirsUser = createOrUpdatePamirsUser(ssoResponseTransient);
}
HttpServletResponse httpServletResponse = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
UserCookieLoginSimple userCookieLoginSimple = new UserCookieLoginSimple();
String sessionId = PamirsSession.getSessionId();
String cacheKey = userCookieLoginSimple.parseSessionId(sessionId);
UserCache.putCache(cacheKey, userCookieLoginSimple.coverToUserDTO(pamirsUser));
PamirsSession.setSessionId(sessionId);
try {
CookieUtil.set(httpServletResponse, UserConstant.USER_SESSION_ID, sessionId);
} catch (Exception e) {
log.error("SSO Login Cookie Set Err", e);
}
//set accessToken to cookies
/**
String userCodeCacheKey = SSOConstant.USER_REDIS_CACHE + pamirsUser.getId();
redisTemplate.opsForValue().set(userCodeCacheKey,accessToken,3600, TimeUnit.SECONDS);
**/
return pamirsUser;
}
// ********这里仅仅是一个示例,在上述情况下创建用户,请根据实际情况处理,请根据实际情况处理*****/
private PamirsUser createOrUpdatePamirsUser(PermissionInfoResp ssoResponseTransient) {
PamirsUser pamirsUser;
pamirsUser = new PamirsUser();
pamirsUser.unsetEmail();
pamirsUser.unsetPhone() ;
pamirsUser.setId(ssoResponseTransient.getUserInfo().getId());
pamirsUser.setUserType(SessionUserTypeEnum.COMPANY_ADMIN.displayName());
pamirsUser.setSignUpType(UserSignUpType.BACKSTAGE);
pamirsUser.setName(ssoResponseTransient.getUserInfo().getUsername());
pamirsUser.setLogin(ssoResponseTransient.getUserInfo().getUsername());
pamirsUser.setNickname(ssoResponseTransient.getUserInfo().getNickname());
pamirsUser.setRealname(ssoResponseTransient.getUserInfo().getNickname());
pamirsUser.setId(ssoResponseTransient.getUserInfo().getId());
userService.createOrUpdate(pamirsUser);
return pamirsUser;
}
/**
* 原始用户登陆后函数调用
* @return
*/
private PamirsUserDTO fetchUserIdByReq4Pamirs() {
PamirsUserDTO pamirsUserDTO = super.fetchUserIdByReq();
if (pamirsUserDTO == null || pamirsUserDTO.getUserId() == null) {
return pamirsUserDTO;
}
PamirsUser user = new PamirsUser().setId(pamirsUserDTO.getUserId()).queryById();
if (user != null && !Boolean.TRUE.equals(user.getActive())) {
//清理下登录的cookie
logout();
log.error("{}当前用户是{},{}", UserExpEnumerate.USER_CAN_NOT_ACTIVE_ERROR, pamirsUserDTO.getUserId(), pamirsUserDTO.getLogin());
throw PamirsException.construct(UserExpEnumerate.USER_CAN_NOT_ACTIVE_ERROR).errThrow();
}
return pamirsUserDTO;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
三、对接SSO示例代码包
示例代码包下载:SS0对接Demo示例