Oauth2授权模式访问之授权码模式(authorization_code)

近期项目上需要将我司系统集成至合作方云平台,双方都有登录,于是改造我司登录模式(我司项目最终会部署至合作方服务器),通过oauth2接入合作方云平台实现获取授权码及token登录本身的项目,下面就实践过程进行记录整理

整体分为以下几个步骤

  1. 调用接口获取授权码
  2. 根据授权码获取accessToken
  3. 换取token、获取用户数据、创建ui参数、将ui参数与token绑定、构建首页地址、登录

下面就三个步骤进行解释:

1.调用接口授权码,oauth2的通用格式 xxx.com/oauth/authorize?client_id=client_id&response_type=code&redirect_uri=http://localhost:xxx/xxx

其中redirect_uri为回调接口,此次过程中为项目中接口,接收授权码回调并进行解析

  • 注:为了与前端解耦将获取授权码、获取token等操作都整合到了步骤3,通过一个回调接口进行登录操作,最后会附上代码进行解释

2.通过接口获取授权码 xxx.com/oauth/token?grant_type=authorization_code&client_id=client_id&client_secret=be4ba6c9-c6f9-bb81-f2df-88381208b8d6&code=8N6TIo&redirect_uri=http://localhost:8081/getloginIDaasCode

{
  "access_token": "436423b4-fc22-4f41-8186-d8706ae9396f",
  "token_type": "bearer",
  "refresh_token": "ce3dd10e-ec60-4399-9076-ee2140b04a61",
  "expires_in": 1999,
  "scope": "read write trust"
}

此时会获取到accessToken,此时已经完成调用,需要将合作方token改造换取成我方token

public OutputMessage loadAccessToken(HttpServletRequest request,HttpServletResponse response,
                            @RequestParam(name = "code")String authCode,
                            @RequestParam(name = "reqUrl",required=false)String reqUrl,
                            @RequestParam(required=false) String state) throws IOException, OAuthProblemException, OAuthSystemException {
   // code为授权码 如8N6TIo
   String homeUrl = publicService.genHomeUrl( authCode,reqUrl );
   WebUtils.issueRedirect(request, response, homeUrl);
   OutputMessage output = new OutputMessage();
   return output;
}

/**
	 *
	 * 1、换取token
	 * 2、获取用户数据
	 * 3、创建ui参数
	 * 4、将ui参数跟token数据进行绑定
	 * 5、构建首页地址
	 */
	@Override
	public String genHomeUrl(String authCode, String reqUrl) throws OAuthSystemException, OAuthProblemException {
        // 转发地址,clientId,秘钥等从数据库获取
		Oauth2Bean oauth2Bean = cuSysConfService.getOauth2Bean();
		//1、该代码块 从token中获取用户信息
		OAuthClientRequest req = OAuthClientRequest
				.tokenLocation(oauth2Bean.getTokenUrl())
				.setClientId(oauth2Bean.getClientId())
				.setClientSecret(oauth2Bean.getClientSecret())
				.setGrantType(GrantType.AUTHORIZATION_CODE).setCode(authCode)
				.setRedirectURI(StringUtils.isEmpty(reqUrl) ? oauth2Bean.getRedirectUrl() : reqUrl)
				.buildBodyMessage();
		req.addHeader("Accept", "application/json");
		req.addHeader("Content-Type", "application/json");

		OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
        // 获取token
		OAuthAccessTokenResponse oauthResponse = oAuthClient.accessToken(req);
		String accessToken = oauthResponse.getAccessToken();

		//2、通过access_token获取userInfo
		OAuthClientRequest bearerClientRequest = new OAuthBearerClientRequest(oauth2Bean.getUserInfo()+"?client_id="+oauth2Bean.getClientId())
				.setAccessToken(accessToken)
				.buildQueryMessage();
		OAuthResourceResponse resourceResponse = oAuthClient.resource(bearerClientRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);
		String userName = resourceResponse.getBody();


		//3、构建UI参数  //"admin:#{"ct":"2022-05-06 11:05:10","reqUrl":"xxx"}#:code_admin";
		String uiTempl = "{}:#{\"ct\":\"{}\",\"reqUrl\":\"{}\"}#:{}"+CommonConstants.authCodeLink+"{}";
		String uiParam = StrUtil.format(uiTempl, userName, DateUtil.getNowDateTimeStr(),reqUrl, authCode,userName);
		CuSysConf UISecretKeyCuSysConf = cuSysConfService.findValidCuSysConfByConfKey(QuVars.sysLoginUIEncryptPubKey);
		if( UISecretKeyCuSysConf == null && UISecretKeyCuSysConf.getConfigValue()!=null ){
			throw new BusinessException("未找到秘钥信息,请联系管理员");
		}
		try {
			uiParam = RSAUtil.encrypt(uiParam, UISecretKeyCuSysConf.getConfigValue().trim() );
		} catch (Exception e) {
			LOG.error(e.getMessage(),e);
			throw new BusinessException( e.getMessage() );
		}
		//4、绑定ui参数
//		cacheDataService.saveAccessToken( authCode+ CommonConstants.authCodeLink+userName ,accessToken );
//		cacheDataService.saveAccessTokenInfo( authCode+CommonConstants.authCodeLink+userName, oauthResponse.getBody() );

		cuUsLoginSService.buildUserPermissionMenu(userName);

		String homeUrl = curesSService.findHomeUrl(userName);
		//5、构建首页地址,拼接首页地址进行转发,如前端参与可不做
		String url = "";
		//如果 reqUrl 不是空就使用此地址作为域名
		if( StrUtil.isNotBlank( reqUrl ) ){
			if (homeUrl.toLowerCase().startsWith("http")){
				homeUrl = homeUrl.toLowerCase()
						.replaceFirst("http://", "")
						.replaceFirst("https://", "");
			}
			String suffixUrl = "";
			if( homeUrl.contains("/") ){
				suffixUrl = homeUrl.substring(homeUrl.indexOf("/"));
			}
			if (reqUrl.toLowerCase().startsWith("http")) {
				url = reqUrl+suffixUrl;
			}else{
				url = "http://"+reqUrl+suffixUrl;
			}
			url = URLUtil.normalize(url);
			url = url+"?UI="+ URLEncoder.encode(uiParam);
		}else{
			url = homeUrl+"?UI="+ URLEncoder.encode(uiParam);
		}
		return url;
	}

最终将构建的地址进行访问即可直接通过token登录我司后台系统,达到接入oauth2系统无感登录。

你可能感兴趣的:(工作日常,java)