公司账号服务单点登录到gitlab

公司账号服务单点登录到gitlab

目标:使用oauth协议,点击挂在系统的gitlab链接,直接登录到gitlab的服务,如果没有账号则新建

操作:
一.服务端:
1.在自己的系统内添加oauth协议的包

<dependency>
			<groupId>org.apache.oltu.oauth2</groupId>
			<artifactId>org.apache.oltu.oauth2.authzserver</artifactId>
			<version>0.31</version>
</dependency>
<dependency>
			<groupId>org.apache.oltu.oauth2</groupId>
			<artifactId>org.apache.oltu.oauth2.resourceserver</artifactId>
			<version>0.31</version>
</dependency>

2.实现和client端交互的三个接口,接口之间的参数验证已经省略
(1).获取客户端 code,没遇到什么问题

import java.net.URI;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.as.issuer.MD5Generator;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.apache.oltu.oauth2.common.message.types.ResponseType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class AuthorizeController {
	private static Logger logger = LoggerFactory.getLogger(AuthorizeController.class);

	@RequestMapping("/responseCode")
	public Object toShowUser(Model model, HttpServletRequest request) {
		logger.info("访问responseCode接口,获取状态码");
		try {
			OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
			//1.验证clientId
			if ("********************".equals(oauthRequest.getClientId())) {
				String authCode = null;
				String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);
				logger.info("responseType:" + responseType);
				// ResponseType仅支持CODE和TOKEN
				if (responseType.equals(ResponseType.CODE.toString())) {
					OAuthIssuerImpl oAuthIssuer = new OAuthIssuerImpl(new MD5Generator());
					authCode = oAuthIssuer.authorizationCode();
				}
				// 进行OAuth响应构建
				OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse
						.authorizationResponse(request, HttpServletResponse.SC_FOUND);
				// 设置授权码,存储用来下一个请求认证
				builder.setCode(authCode);
				// 得到到客户端重定向地址
				String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);
				logger.info("redirectURI:" + redirectURI);
				// 构建响应
				final OAuthResponse response = builder.location(redirectURI).buildQueryMessage();
				String responceUri = response.getLocationUri();
				// 根据OAuthResponse返回ResponseEntity响应
				HttpHeaders headers = new HttpHeaders();
				try {
					headers.setLocation(new URI(response.getLocationUri()));
				} catch (Exception e) {
					e.printStackTrace();
				}
				return "redirect:" + responceUri;
			}
		} catch (Exception e) {
		}
		return null;
	}
}

(2)生成access_token,在这块卡了很长时间,原因是返回值是Map的形式,gitlab官方也没有找到对返回值的规范,就写出来记录一下吧。

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.oltu.oauth2.as.issuer.OAuthIssuer;
import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl;
import org.apache.oltu.oauth2.as.issuer.UUIDValueGenerator;
import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
import org.apache.oltu.oauth2.as.response.OAuthASResponse;
import org.apache.oltu.oauth2.common.OAuth;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.apache.oltu.oauth2.common.message.OAuthResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;

@Controller
public class AccessTokenController {

	private static Logger logger = LoggerFactory.getLogger(AccessTokenController.class);

	// 获取客户端的code码,向客户端返回access token
	@RequestMapping(value = "/responseAccessToken",method = RequestMethod.POST)
	@ResponseBody
	public Object token(HttpServletRequest request) {
		logger.info("访问responseAccessToken接口        获取access_token");
		OAuthIssuer oauthIssuerImpl = null;
		OAuthResponse response = null;
		// 构建OAuth请求
		try {
			OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);
			// 1.验证authcode
			String authCode = oauthRequest.getParam(OAuth.OAUTH_CODE);
		
			// 2.验证clientSecret
			String clientSecret = oauthRequest.getClientSecret();
			logger.info("clientSecret:" + clientSecret);

			// 3.生成Access Token
			oauthIssuerImpl = new OAuthIssuerImpl(new UUIDValueGenerator());
			final String accessToken = oauthIssuerImpl.accessToken();			
			Map<String,String> resultMap = new HashMap<String,String>();
			resultMap.put("access_token", accessToken);
			resultMap.put("expires_in", "0");
			return resultMap;
		} catch (OAuthSystemException e) {
			e.printStackTrace();
		} catch (OAuthProblemException e) {
			e.printStackTrace();
		}
		return null;
	}
}

(3).通过access_token获取账号信息,这块的遇到的问题主要有两个,第一个是在request中没有取到access_token,试着打印了http完整的请求,发现在request之前会打印完整信息,但是request是取不到的,具体获取方法先如下。第二个问题是,用户同步的问题,id(感觉是为了保证唯一性,否则每次都是新建的账号),name,nickname,email,这四个参数是可以满足,新建gitlab账号,正常单点登录的问题。

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.oltu.oauth2.as.request.OAuthUnauthenticatedTokenRequest;
import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;

@Controller
public class UserInfoController {
	private static Logger logger = LoggerFactory.getLogger(UserInfoController.class);

	@RequestMapping("/userInfo")
	@ResponseBody
	public Object userInfo(HttpServletRequest request) {
		logger.info("访问userInfo接口  获取账号信息");
		
		String header = request.getHeader("authorization");
		String[] split = header.split(" ");
		String accesstoken = split[1].trim();
		// 1.验证token
		//1.1验证token的过期时间
		
		String username = commonUtils.getUsernameByToken(accesstoken);
		if (StringUtils.isBlank(username)) {
			return "";
		}
		// 2.取到账号信息返回
		Map<String, Object> resultMap = new HashMap<String, Object>();
		if ("zhangsan".equals(username)) {
			resultMap.put("id", "111");
			resultMap.put("name", "zhangsan");
			resultMap.put("nickname", "zhangsan");
			resultMap.put("email", "******@163.com");
		} else if ("lisi".equals(username)) {
			resultMap.put("id", "112");
			resultMap.put("name", "lisi");
			resultMap.put("nickname", "lisi");
			resultMap.put("email", "lisi@163.com");
		} 
		logger.info(JSON.toJSONString(resultMap));
		ResponseEntity<Object> responseEntity = new ResponseEntity<Object>(resultMap, HttpStatus.valueOf(200));
		return responseEntity;
	}
}

二,是客户端gitlab的配置,主要修改 /etc/gitlab/gitlab.rb文件
配置的含义可以看gitlab官方解释,具体配置app_id和app_secret 自己和服务端关联起来就好,三个接口可以自己定义,gitlab有默认接口:

 user_info_url: '/api/v3/user', # The endpoint on your OAuth 2 server that provides user info for the current user
 authorize_url: '/oauth/authorize', # The authorization endpoint for your OAuth server
 token_url: '/oauth/token' # The token request endpoint for your OAuth server

具体查看 oauth2_generic.rb 文件,忘了在哪个目录了

gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_allow_single_sign_on'] = ['****']
gitlab_rails['omniauth_block_auto_created_users'] = false
#gitlab_rails['omniauth_auto_sign_in_with_provider'] = '****'
gitlab_rails['omniauth_providers'] = [
  {
    'name' => '****',
    #'app_id' => '67bc4a4b7515a2cc5a31ab91d8bf953f68b21b08b701dc20c6102eec65d80e9c',
    #'app_secret' => 'b9ca8154f8efc888ed95a44161ed1237fb0b8a84ea7fe2532eb879f812cf73d8',
    'app_id' => '67bc4a4b7515a2cc5a31ab91d8bf953f68b21b08b701dc20c',
    'app_secret' => 'b9ca8154f8efc888ed95a44161ed1237fb0b8a84ea7fe253',
    'args' => {
      client_options: {
        'site' => 'http://127.0.0.1:8080', 
        'authorize_url' => '/v1/sso/responseCode',
        'token_url' => '/v1/sso/responseAccessToken',
        'user_info_url' => '/v1/sso/userInfo'
      },
      user_response_structure: {
        root_path: [],
        id_path: 'id',
        attributes: { 
        	name: 'name',
        	nickname: 'nickname',
			email: 'email'
        }
      },
      name: '****', 
      strategy_class: "OmniAuth::Strategies::OAuth2Generic"   
    }
  }
]

至此,是可以满足正常的单点登录啦。
出现过的问题:

  1. 导航栏: 邮箱已经别注册,gitlab是一个邮箱对应一个账号
  2. 客户端会做token是否过期的判断,注意过期时间
  3. 对于gitlab已有的账号,需要关联一下账号 操作步骤:正常登录–>setting–>account–>Connected Accounts

还有剩余问题:
测试中出现

还有遇到的问题欢迎大家评论探讨。、
有帮助的话记得收藏点赞,谢谢。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值