參考:
https://developer.linkedin.com/docs/oauth2
https://developer.linkedin.com/docs/signin-with-linkedin
準備工作:
注冊一個開發号在建立一個Web應用,網址: https://www.linkedin.com/developer/apps
需求:點選使用linkedIn登入圖示,調轉到linkedIn授權頁面。點選允許登入網址。
開發:
第一步擷取Code:
Controller:
@RequestMapping(value = "/toLogin")
public void weixinLogin(HttpServletRequest request,HttpServletResponse response){
String appid=PropertiesUtils.getProperty("system.linkedIn.clientId");
int serverPost = request.getServerPort();
String basePath = null;
if(serverPost==80){
basePath = request.getScheme()+"://"+request.getServerName()+request.getContextPath();
}else{
basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
}
String redirectUri=basePath+"/linkedIn/loginProcess";
String code="code";
String state=MyTools.generateString(20);
HttpSession session = request.getSession();
session.setAttribute("linkcode", state);
String baseUrl="https://www.linkedin.com/oauth/v2/authorization";
linkedInHelper.toLoginPage(baseUrl, appid, redirectUri, code, "", state,response);
}
LinkedInAPI.java:
public boolean toLoginPage(String baseUrl,String clientId,String redirectUri,String code,String scope,String state,HttpServletResponse response){
try {
String redirectUriCode = URLEncoder.encode(redirectUri,"utf-8");//坑1
baseUrl+="?client_id="+clientId+"&redirect_uri="+redirectUriCode+"&response_type="+code+"&scope="+scope+"&state="+state+"&format=json";
try {
response.sendRedirect(baseUrl);
} catch (IOException e) {
log.error("URLEncoder重定向位址失敗,請求取消");
e.printStackTrace();
return false;
}
return true;
} catch (UnsupportedEncodingException e) {
log.error("URLEncoder重定向位址失敗,請求取消");
e.printStackTrace();
return false;
}
}
第二步擷取Token,然後擷取使用者資訊登入網址:
@RequestMapping(value = "/loginProcess")
public ModelAndView LoginProcess( HttpServletRequest request){
ModelAndView mav=new ModelAndView();
String code=request.getParameter("code");
String status=request.getParameter("state");
String tempCode=(String)request.getSession().getAttribute("linkcode");
request.getSession().removeAttribute("linkcode");
/*防止跨站攻擊*/
if(null==tempCode||null==status||!tempCode.trim().equalsIgnoreCase(status.trim())){
mav.setViewName("/error404");
mav.addObject("msg", "疑似跨站攻擊");
return mav;
}
/*判斷第一步是否得到Code*/
if(MyTools.isEmptyStr(code)){
//登入失敗處理
mav.setViewName("/error404");
String errorDes=request.getParameter("error_description");
mav.addObject("msg",errorDes);
return mav;
}else{
String appid=PropertiesUtils.getProperty("system.linkedIn.clientId");
String secret=PropertiesUtils.getProperty("system.linkedIn.clientSecret");
String getTokenUrl="https://www.linkedin.com/oauth/v2/accessToken";
int serverPost = request.getServerPort();
String basePath = null;
if(serverPost==80){
basePath = request.getScheme()+"://"+request.getServerName()+request.getContextPath();
}else{
basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath();
}
String redirectUri=basePath+"/linkedIn/loginProcess";
JSONObject tokenInfo=linkedInHelper.getAccessToken(getTokenUrl, appid, secret, code, "authorization_code", redirectUri);
if(null==tokenInfo){
mav.setViewName("/error404");
mav.addObject("msg", "HTTP請求出錯!");
return mav;
}
if(!tokenInfo.containsKey("access_token")){
/*擷取Token失敗處理*/
//登入失敗處理
mav.setViewName("/error404");
mav.addObject("msg","擷取令牌失敗");
return mav;
}else{
/*用Token擷取使用者資訊*/
String accessToken=tokenInfo.getString("access_token");
if(MyTools.isEmptyStr(accessToken)){
/*擷取Token失敗處理*/
//登入失敗處理
mav.setViewName("/error404");
mav.addObject("msg","擷取令牌失敗");
return mav;
}
String getUserInfoUrl="https://api.linkedin.com/v1/people/~";
JSONObject userInfo=linkedInHelper.getUserInfo(getUserInfoUrl, accessToken);
if(!userInfo.containsKey("id")){
/*擷取資訊失敗*/
mav.setViewName("/error404");
mav.addObject("msg", tokenInfo.get("errmsg"));
return mav;
}else{
/*擷取資訊成功*/
//儲存使用者
UserInfo user=new UserInfo();
user.setName(userInfo.getString("firstName")+" "+userInfo.getString("lastName"));
user.setUid(userInfo.getString("id"));
user.setLinkedInId(userInfo.getString("id"));
user.setCreateDate(new Date());
user.setEnabled(1);
user.setType(1);
user.setRegisterSource(2);
user.setRegisterCode(MyTools.generateString(30));
userService.saveUserInfo(user);
InsideUsernamePasswordToken token = new InsideUsernamePasswordToken();
token.setUsername(userInfo.getString("id"));
//****—****#####登入處理代碼
token.setRememberMe(false);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
mav.setViewName("redirect:/index");
return mav;
}
}
}
}
LinkedInAPI:
/**
* 擷取令牌
* @param baseUrl
* @param clientId
* @param secret
* @param code 第一步中得到的
* @param grantType 填authorization_code
* @param redirectUri
* @return access_token and expires_in
* 建立時間:2016年11月9日 下午2:11:11
*/
public JSONObject getAccessToken(String baseUrl,String clientId,String secret,String code,String grantType,String redirectUri){
try {
String redirectUriCode = URLEncoder.encode(redirectUri,"utf-8");//對應坑1
baseUrl+="?client_id="+clientId+"&client_secret="+secret+"&code="+code+"&grant_type="+grantType+"&redirect_uri="+redirectUriCode+"&format=json";
String resultJson=HttpHelper.doPostForLinkedIn(baseUrl,"");
return JSONObject.parseObject(resultJson);
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
/**
* 擷取使用者的基本資訊
* @param baseUrl
* @param accessToken
* @return
* 建立時間:2016年11月9日 下午3:29:29
*/
public JSONObject getUserInfo(String baseUrl,String accessToken){
String resultJson=HttpHelper.doGet(baseUrl+"?"+"format=json","Bearer "+accessToken);//坑2,token放到這裡
return JSONObject.parseObject(resultJson);
}
HttpHelper.java
public static String doGet(String strURL,String authorizationStr){
String result="";
try{
URL url = new URL(strURL);// 建立連接配接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("GET"); // 設定請求方式
connection.setRequestProperty("Accept", "application/json"); // 設定接收資料的格式
connection.setRequestProperty("Content-Type", "application/json"); // 設定發送資料的格式
connection.setRequestProperty("Authorization",authorizationStr);//對應坑2,token放到這裡
connection.connect();
// 處理響應資料
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} finally {
if(in!=null) in.close();
}
}catch(Exception e){
StackTraceElement stes[]=e.getStackTrace();
log.info(HttpHelper.class.toString()+"function:doGet");
log.info("---------------------http請求位址-----------------------");
log.info(strURL);
log.info("---------------------http請求内容-----------------------");
log.info(result);
for(StackTraceElement ste:stes){
log.error(ste.getFileName()+":"+ste.getLineNumber()+":"+ste.getMethodName());
}
}
return result;
}
public static String doPostForLinkedIn(String strURL, String jsonParams){
String result = "";
try{
URL url = new URL(strURL);// 建立連接配接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
// connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("POST"); // 設定請求方式
//坑3 application/x-www-form-urlencoded
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 設定發送資料的格式
connection.connect();
PrintWriter out = new PrintWriter(connection.getOutputStream());
System.out.println("helper==="+jsonParams+"===");
try {
out.print(jsonParams);
out.flush();
} finally {
if(out!=null) out.close();
}
// 處理響應資料
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} finally {
if(in!=null) in.close();
}
}catch(Exception e){
log.info(HttpHelper.class.toString());
log.info("---------------------http請求位址-----------------------");
log.info(strURL);
log.info("---------------------http請求内容-----------------------");
log.info(result);
StackTraceElement stes[]=e.getStackTrace();
for(StackTraceElement ste:stes){
log.error(ste.getFileName()+":"+ste.getLineNumber()+":"+ste.getMethodName());
}
e.printStackTrace();
}
return result;
}