需求描述:
一套应用服务,有自己的独立登录接口,独立认证服务(JWT认证),独立用户等,需要接入第三方的统一认证系统,实现用户统一登录;
需求分析:
实现统一用户和单点登录,需要是:
首先用户同步,用户数量小,可以通过手动新建,然后和统一用户关联的方式;
> 对于只有统一登录,不需要统一用户的,需要自动新建用户或关联已有用户
- 其次是统一登录页面:可以保留自有登录页面,通过不同接口跳转到统一登录页面做验证;
- jwt方式不提供统一登出服务;
需求实现说明
- 用户同步:先手动新建,或在登录时自动新建,或先同步用户信息;
- 提供登陆接口:在应用中提供一个新的登录接口(restful接口),跳转的统一登录页,在跳转过程中提供必要参数;
- 统一登录回调: 在应用中提供一个统一登录后的回调接口,用于验证是否登录成功;
- 生成应用JWT:在统一登录结果验证成功后,则生成应用中的jwt,放置到Cookie中,跳转到应用页面;
- 验证jwt: 在应用页面中验证jwt,jwt是应用生成,是可用的;
代码实现:
- 用户同步:可用手动新建测试;
提供登录跳转接口:
Oauth2.0认证服务一般会提供一个登录地址:传递以下参数:
一个登陆成功的回调地址redirectUri
一个原值返回的参数state,一般会填写登录后的跳转页面
统一认证系统应用的id和secret
以下代码提供了一个登录接口,跳转的统一登录页面,并携带指定参数;
public void login(HttpServletRequest request, HttpServletResponse response,String redirect_uri) {
String contextPath = request.getContextPath();
String redirectUri = serverUri + contextPath + "/api/authsuccess";
//->/api/authsuccess是应用提供的验证地址
logger.info("认证成功之后调转到目标地址为:redirectUri:{}", redirectUri);
String url = UriComponentsBuilder.fromUriString(authorizeUrl).queryParam("app_id", clientId)
.queryParam("app_secret", clientSecret).queryParam("state", redirect_uri)
.queryParam("redirect_uri", redirectUri).build().encode().toUriString();
response.sendRedirect(url);
}
在统一登录页面,用户输入用户名密码登录,通过成功后,回调应用上一步登录验证接口;
用户登录成功,统一认证服务会保存应用系统的Session,在下次通过应用跳转其他系统时,会获取到这个session判断是否登录,若已登录,在不会出现登录窗口Oauth2.0一般情况下,会返回一个code给应用;
应用接收code,通过统一登录接口,获取登录用户ID
应用获取登录用户ID,生成JWTtoken
将jwt_token放置到cookie中,跳转的指定页面
// state为上一步传递的参数
public void authenticate(HttpServletRequest request, HttpServletResponse response, String code,
String state) {
Map<String, Object> userInfo = getUserInfo(code); //获取用户信息
String userId = (String) userInfo.get("username");
String _jwt = generateToken(userId);
String jwt_iss = (System.currentTimeMillis()/ 1000) + "";
String jwt_expire = (30 * 1000) + "";
Cookie jwt_cookie = new Cookie("_jwt", jwt);
Cookie jwtActiveCookie = new Cookie("_jwt_active", jwt_iss );
Cookie jwtExpireTimeCookie = new Cookie("_jwt_exp", jwt_expire );
jwtCookie.setPath("/");
jwtActiveCookie.setPath("/");
jwtExpireTimeCookie.setPath("/");
response.addCookie(jwtCookie);
response.addCookie(jwtActiveCookie);
response.addCookie(jwtExpireTimeCookie);
response.sendRedirect(state);
}
- 跳转后的页面为应用页面,在调用应用接口时,会验证jwt是否有效
接入完成;
其他接入方式,可能接口不同,但是流程应该大致相似;