Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin

Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin

(Xem thêm: code ví dụ JSP Servlet login bằng Facebook)

(Xem thêm: Code ví dụ JSP Servlet login bằng Google (Gmail/Google+))

Tạo một ứng dụng trên LinkedIn.

(Xem lại: Tạo ứng dụng Linkedin để đăng nhập thay tài khoản)

Ở đây mình tạo ứng dụng “stackjava.com – JSPServlet” với  Client ID = “81b7a9xubzdq1u” và Client Secret = “anbyTSAldwhA28GY”

Tạo ứng dụng login linkedin

 Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin stackjava.com

Tạo ứng dụng Java Web với JSP – Servlet

Ở đây mình dùng server là tomcat 8

Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin

Mình dùng thư viện org.apache.httpcomponents (httpclient, httpcore, fluent) để gửi request từ bên trong class servlet, thư viện gson để convert dữ liệu từ dạng json và ngược lại. (mấy chức năng này viết khá dài nên mình dùng thư viên cho nhanh)

(Download các thư viện trên tại đây)

Class Constants.java:

Dùng để lưu client_id, client_secret, redirect_uri của ứng dung “stackjava.com – JSPServlet”

package stackjava.com.accesslinkedin.common;

public class Constants {
  public static String LINKEDIN_CLIENT_ID = "81b7a9xubzdq1u";
  public static String LINKEDIN_CLIENT_SECRET = "anbyTSAldwhA28GY";
  public static String LINKEDIN_REDIRECT_URI = "http://localhost:8080/AccessLinkedIn/login-linkedin";
  public static String LINKEDIN_LINK_GET_TOKEN = "https://www.linkedin.com/oauth/v2/accessToken";
  public static String LINKEDIN_GRANT_TYPE = "authorization_code";
  public static String LINKEDIN_LINK_GET_USER_INFO = "https://api.linkedin.com/v1/people/~?format=json&oauth2_access_token=";
}

Trang login

<html>
<head>
  <title>Login</title>
</head>
<body>
  <h1>Demo Login with LinkedIn</h1>
  <a href="https://www.linkedin.com/oauth/v2/authorization?response_type=code&client_id=81b7a9xubzdq1u
  &redirect_uri=http://localhost:8080/AccessLinkedIn/login-linkedin&scope=r_basicprofile">Login With Linkedin</a>	
</body>
</html>

Đường link https://www.linkedin.com/oauth/v2/...scope=r_basicprofile dùng để gọi hộp thoại đăng nhập và cài đặt URL chuyển hướng:

url chuyển hướng đăng nhập linkedin

Sau khi bạn cho phép ứng dụng truy cập các thông tin tài khoản của LinkedIn, LinkedIn sẽ gửi một đoạn mã (code) tới url “http://localhost:8080/AccessLinkedIn/login-linkedin” để server của bạn xử lý.

  • Nếu bạn đồng ý thì redirect uri trả về sẽ có 2 tham số code (OAuth 2.0 authorization code) và state ( dùng cho CRSF)
  • Nếu bạn không đồng ý thì redirect uri trả về sẽ kèm 3 than số là error_code, error_description và state

Class Servlet

package stackjava.com.accesslinkedin.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import stackjava.com.accesslinkedin.common.User;
import stackjava.com.accesslinkedin.common.LinkedInUtils;

@WebServlet("/login-linkedin")
public class LoginLinkedinServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public LoginLinkedinServlet() {
    super();
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    String code = request.getParameter("code");

    if (code == null || code.isEmpty()) {
      RequestDispatcher dis = request.getRequestDispatcher("login.jsp");
      dis.forward(request, response);
    } else {
      String accessToken = LinkedInUtils.getToken(code);
      User user = LinkedInUtils.getUserInfo(accessToken);
      request.setAttribute("id", user.getId());
      request.setAttribute("name", user.getName());
      RequestDispatcher dis = request.getRequestDispatcher("index.jsp");
      dis.forward(request, response);
    }

  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    doGet(request, response);
  }

}

LoginLinkedinServlet.java sẽ nhận đoạn mã trả về từ linkedin, đổi mã đó thành access-token rồi dùng access-token để truy cập các thông tin trong tài khoản linkedin như name, id…

Class LinkedInUtils.java dùng để gửi truy vấn tới linkedin (đổi code sang access-token, lấy thông tin trong tài khoản linkedin)

package stackjava.com.accesslinkedin.common;

import java.io.IOException;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.fluent.Form;
import org.apache.http.client.fluent.Request;

import com.google.gson.Gson;
import com.google.gson.JsonObject;

public class LinkedInUtils {

  public static String getToken(final String code) throws ClientProtocolException, IOException {

    String response = Request.Post(Constants.LINKEDIN_LINK_GET_TOKEN)
        .bodyForm(Form.form().add("client_id", Constants.LINKEDIN_CLIENT_ID)
            .add("client_secret", Constants.LINKEDIN_CLIENT_SECRET)
            .add("redirect_uri", Constants.LINKEDIN_REDIRECT_URI).add("code", code)
            .add("grant_type", Constants.LINKEDIN_GRANT_TYPE).build())
        .execute().returnContent().asString();

    JsonObject jobj = new Gson().fromJson(response, JsonObject.class);
    String accessToken = jobj.get("access_token").toString().replaceAll("\"", "");
    return accessToken;
  }

  public static User getUserInfo(final String accessToken) throws ClientProtocolException, IOException {
    String link = Constants.LINKEDIN_LINK_GET_USER_INFO + accessToken;
    String response = Request.Get(link).execute().returnContent().asString();
    JsonObject jobj = new Gson().fromJson(response, JsonObject.class);
    String id = jobj.get("id").toString().replaceAll("\"", "");
    String firstName = jobj.get("firstName").toString().replaceAll("\"", "");
    String lastName = jobj.get("lastName").toString().replaceAll("\"", "");
    String name = firstName + lastName;
    User user = new User(id, name);
    return user;

  }

}

Đường link lấy thông tin tài khoản linkedin sẽ có dạng:
https://api.linkedin.com/v1/people/~?format=json&oauth2_access_token=your_accesstoken

Thông tin trả về tùy vào permission mà ứng dụng được cấp, ở đây mình chỉ yêu cầu permission là  r_basicprofile nên thông tin trả về sẽ gồm:

{
  "firstName": "...",
  "headline": "...",
  "id": "...",
  "lastName": "...",
  "siteStandardProfileRequest": {
    "url": "https://www.linkedin.com/profile/view?id=…"
  }
}

Class User.java để lưu thông tin tài khoản từ linkedin

package stackjava.com.accesslinkedin.common;

public class User {
  private String id;
  private String name;

  // getter - setter

}

Trang index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<html>
<head>
<title>index</title>
</head>
<body>
  <h1>Index</h1>
  <%
    String id = request.getAttribute("id").toString();
    String name = request.getAttribute("name").toString();
    out.print("Id: " + id);
    out.print("<br/>Name: " + name);
  %>
</body>
</html>

Demo:

Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin

Trường hợp không cho phép ứng dụng “stackjava.com – JSPServlet” truy cập thông tin tài khoản:

Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin

Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin

Trường hợp cho phép ứng dụng “stackjava.com – JSPServlet” truy cập thông tin tài khoản:

 Code ví dụ JSP Servlet đăng nhập (login) bằng Linkedin stackjava.com

Okay, Done!

Download code ví dụ trên tại đây.

 

References.

https://developer.linkedin.com/docs/oauth2

https://developer.linkedin.com/docs/signin-with-linkedin#

 

stackjava.com