为您提供有关LinkedIn的一些信息:
LinkedIn no longer supports the JavaScript SDK. The recommended approach is to use OAuth 2.0 and LinkedIn's Auth APIs.
和:
LinkedIn does not support TLS 1.0. Support for TLS 1.1 has been marked for deprecation starting 02/01/2020. Please use TLS 1.2 when calling LinkedIn APIs. All API requests to api.linkedin.com must be made over HTTPS. Calls made over HTTP will fail.
Step 1
:为Javascript库添加Jquery,运行命令:
$ yarn add jquery
然后,设置 config/webpack/environment.js 的内容:
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')
environment.plugins.prepend('Provide',
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jQuery: 'jquery/src/jquery'
})
)
module.exports = environment
Step 2
: 通过添加thin
gem创建 ssl 连接
gem 'thin'
$ bundle install
编辑config/application.rb
并添加:
config.force_ssl = true
在项目命令行中,键入:
$ openssl genrsa 2048 > host.key
$ chmod 400 host.key
$ openssl req -new -x509 -nodes -sha256 -days 365 -key host.key -out host.cert
在这些命令之后将创建两个文件:host.key
和host.cert
. 然后运行:
$ thin start --ssl --ssl-key-file=./host.key --ssl-cert-file=./host.cert
它将在默认地址运行项目:https://0.0.0.0:3000。如果你想在 https://localhost:3000 上运行,只需输入:
$ thin start -a localhost --ssl --ssl-key-file=./host.key --ssl-cert-file=./host.cert
Step 3
:创建Linkedin oauth2 应用程序。
转到链接:https://www.linkedin.com/developers/
单击按钮Create app
,然后将信息填写到应用名称、LinkedIn 页面(必须通过自定义页面完成)、应用徽标、条款复选框。然后单击创建应用程序以注册您的应用程序。
在设置选项卡上,设置应用程序的域,我使用 localhost 运行,所以我将设置https://localhost:3000
.
在 Auth 选项卡中,将 Client ID 和 Client Secret 保存到config/application.yml
(记得在此之前运行命令$ bundle exec figaro install
),如下所示:
LINKEDIN_APP_ID: 86g3...sfjm
LINKEDIN_APP_SECRET: OKnb...jzSL
然后为您的应用编辑、输入和保存部分授权重定向 URL:
https://localhost:3000/auth/linkedin/callback
检查可在此页面中使用的范围!我的是r_emailaddress r_liteprofile
。
在产品选项卡上,选择Sign In with LinkedIn
,状态将更改为Review in progress
。如果刷新 F5 一段时间后此状态消失,则一切正常!
Step 4
:像我一样设置所有代码。简单config/routes.rb
:
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "omniauth_callbacks" }
get '/auth/linkedin/callback', to: "linkedin#callback"
post '/auth/linkedin/url', to: "linkedin#popup"
post '/auth/linkedin/token', to: "linkedin#get_token"
post '/auth/linkedin/info', to: "linkedin#get_info"
post '/auth/linkedin/out', to: "linkedin#stop"
root to: "linkedin#home"
end
使用内容创建app/controllers/linkedin_controller.rb
:
class LinkedinController < ApplicationController
# Lib to get token
require "uri"
require "net/http"
# Data variables set/get
attr_accessor :client_id, :client_secret, :redirect_uri, :scope, :raise_error
# Class variable with 2@
@@token = ""
# Return view linkedins/home page
def home
render 'linkedins/home'
end
# Call back from popup login window of LinkedIn site
def callback
Rails.logger.debug "Callback called! Params:"
Rails.logger.debug params
@code = params[:code]
@state = params[:state]
@redirect = '/auth/linkedin/callback'
# Get token
url = URI("https://www.linkedin.com/oauth/v2/accessToken")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
host_uri = ENV['HOST']+@redirect
request.body = "grant_type=authorization_code&code=#{@code}&client_id=#{ENV['LINKEDIN_APP_ID']}&client_secret=#{ENV['LINKEDIN_APP_SECRET']}&redirect_uri=#{host_uri}"
response = https.request(request)
Rails.logger.debug "response.read_body:"
# Rails.logger.debug response.read_body
r = JSON.parse(response.read_body)
Rails.logger.debug r["access_token"]
@@token = r["access_token"]
render 'linkedins/callback'
end
# Config init values
def start
@client_id = ENV['LINKEDIN_APP_ID']
@client_secret = ENV['LINKEDIN_APP_SECRET']
@raise_error = 'true'
@redirect = '/auth/linkedin/callback'
@redirect_uri = ENV['HOST']+@redirect
@scope = 'r_emailaddress r_liteprofile'
@state = generate_csrf_token
end
# Return popup url for sign in by LinkedIn, method = POST
def popup
self.start
@url = "https://www.linkedin.com/uas/oauth2/authorization?client_id=#{@client_id}&raise_errors=#{@raise_error}&redirect_uri=#{@redirect_uri}&response_type=code&scope=#{@scope}&state=#{@state}"
# return @url
render json: { status: 'Success', message: 'Load url for popup finished!', link: @url},status: :ok
end
# Get token of current account Linkedin logged
def get_token
Rails.logger.debug 'From get_token, @@token cache:'
Rails.logger.debug @@token
render json: { status: 'Success', message: 'Load token finished!', token: @@token},status: :ok
end
# Get basic info
def get_info
Rails.logger.debug 'From get_info!'
# Create custom api linking
fields = ['id', 'firstName', 'lastName', 'profilePicture']
link = "https://api.linkedin.com/v2/me?projection=(#{ fields.join(',') })"
url = URI(link)
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = "Bearer #{@@token}"
response = https.request(request)
Rails.logger.debug "From get_info, variable response:"
Rails.logger.debug response
r = JSON.parse(response.read_body)
# r = JSON.parse(response.body)
first_name = r['firstName']['localized']['en_US'].to_s
last_name = r['lastName']['localized']['en_US'].to_s
full_name = first_name + " " + last_name
render json: { status: 'Success',message: 'Load link basic info finished!', name: full_name},status: :ok
end
# For logout LinkedIn, by method revoke
def stop
link = 'https://www.linkedin.com/oauth/v2/revoke'
url = URI(link)
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = "application/x-www-form-urlencoded"
request.body = "client_id=#{ENV['LINKEDIN_APP_ID']}&client_secret=#{ENV['LINKEDIN_APP_SECRET']}&token=#{@@token}"
response = https.request(request)
Rails.logger.debug "Test logout linkedin!"
render json: { status: 'Success',message: 'Log out finished!'},status: :ok
end
# Genereate random state
def generate_csrf_token
SecureRandom.base64(32)
end
end
注意安装这些 gem,我们不需要任何 oauth2 链接库:
gem 'uri'
gem 'net-http'
$ bundle install
我们将通过此回调视图退出弹出式 LinkedIn 登录app/views/linkedins/callback.html.erb
:
<script>
// Close this popup show from LinkedIn window open
close();
</script>
创建这个主视图app/views/linkedins/home.html.erb
:
<p>Linkedin Login Home page</p>
<button id="linkedin-login" type="button">Login</button>
<p id="linkedin-informations">Token here!</p>
<button id="linkedin-logout" type="button">Logout</button>
<p id="linkedin-results">Results here!</p>
<script>
$('#linkedin-login').on('click', function(e){
// e.preventDefault()
var url_popup = ""
var ltoken = ""
var lurl = ""
$.post('/auth/linkedin/url', function(json) {
console.log(json)
url_popup = json.link
if (url_popup != "") {
console.log('Successful to load url popup!')
const w = 600
const h = 600
const top = (screen.height - h) / 4, left = (screen.width - w) / 2
var child = window.open(url_popup, "popupWindow", `width=${w}, height=${h}, top=${top}, left=${left}, scrollbars=yes`)
function checkChild() {
if (child.closed) {
clearInterval(timer);
$.post('/auth/linkedin/token', function(json) {
console.log('Load token link successful!')
$('#linkedin-informations').html('Token is comming ...')
ltoken = json.token
console.log(json.token)
$('#linkedin-informations').html(json.token)
})
$.post('/auth/linkedin/info', function(json) {
console.log('Load info link successful!')
$('#linkedin-results').html('Information is comming ...')
console.log(json)
$('#linkedin-results').html(`Your login account: ${json.name}`)
})
}
}
var timer = setInterval(checkChild, 500);
}
})
})
$('#linkedin-logout').on('click', function(e){
e.preventDefault()
$.post('/auth/linkedin/out', function(json) {
console.log('Log out successful!')
$('#linkedin-results').html(`You logged out!`)
})
})
</script>
成功画面: