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系统无感登录。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于 Python,你可以使用第三方库来实现 OAuth2 授权。其中最常用的库是 `requests-oauthlib`。以下是一个简单的示例代,展示了如何使用该库进行 OAuth2 授权: ```python from requests_oauthlib import OAuth2Session # 定义授权参数 client_id = 'YOUR_CLIENT_ID' client_secret = 'YOUR_CLIENT_SECRET' authorization_base_url = 'AUTHORIZATION_URL' token_url = 'TOKEN_URL' redirect_uri = 'REDIRECT_URI' # 创建 OAuth2Session 对象 oauth = OAuth2Session(client_id, redirect_uri=redirect_uri) # 生成授权 URL authorization_url, _ = oauth.authorization_url(authorization_base_url) # 打印授权 URL,并在浏览器中访问进行授权 print(f'请在浏览器中访问以下 URL 进行授权: {authorization_url}') # 获取授权 authorization_code = input('请输入授权: ') # 使用授权获取访问令牌 token = oauth.fetch_token( token_url, code=authorization_code, client_secret=client_secret ) # 使用访问令牌发送请求 response = oauth.get('API_ENDPOINT') print(response.json()) ``` 请注意,以上代中的参数需要根据你的实际情况进行修改,包括 `client_id`、`client_secret`、`authorization_base_url`、`token_url`、`redirect_uri` 和 `API_ENDPOINT`。你需要根据你使用的 OAuth2 提供商的文档来获取这些参数。 此外,还有其他一些流行的 Python OAuth2 库可以使用,如 `authlib`、`python-oauth2` 等,你可以根据自己的需求选择适合你的库来实现 OAuth2 授权

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值