第三方登錄
1.第三方程序:
? ? ?比如 微信 ? QQ ? github ? 碼云 ? csdn.....
2.使用目的
? ? ?第三方程序 方便 ? ? ?社交軟件用戶量相當(dāng)大
3.第三方登錄實(shí)現(xiàn)原理
普通登錄:數(shù)據(jù)庫用戶名和密碼進(jìn)行對(duì)比。使用shiro登錄胰蝠。sso單點(diǎn)登錄歼培。第三方
OAuth2.0授權(quán)碼模式
OAUTH協(xié)議為用戶資源的授權(quán)提供了一個(gè)安全的、開放而有簡易的標(biāo)準(zhǔn)茸塞。
思路
- 1.獲得授權(quán)碼
- 2.通過授權(quán)碼那令牌
- 3.通過令牌拿資源
這三步最核心丐怯,簡單的說就是要拿到三個(gè)url。其他的微信都做完了翔横,拿過來用就行了。
流程
1.通過url獲得授權(quán)碼
1.1.需要填寫appid
1.2.需要寫回調(diào)函數(shù)(用域名)
2.第二個(gè)url通過第一部獲得授權(quán)碼去申請(qǐng)令牌
2.1令牌返回的是json梗搅,需要去里面的access_token傳遞秘鑰
3.通過令牌獲得用戶信息
-
第一個(gè)url----請(qǐng)求CODE
第一個(gè)url:CODE參數(shù)介紹 第二個(gè)url----通過code獲取access_token
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
- 第三個(gè)url ---- 通過access_token調(diào)用接口
http請(qǐng)求方式: GET
https://api.weixin.qq.com/sns/oauth2/access_token ?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
案例
1.首先在微信平臺(tái)注冊(cè)平臺(tái)開發(fā)者
官網(wǎng):https://open.weixin.qq.com/
QQ互聯(lián)
官方網(wǎng)址:
還需要其他的就是上碼云看禾唁,全都有,只有你想不到的无切,沒有你找不到的
2.導(dǎo)包 web-里pom.xml(util)
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<!-- 遠(yuǎn)程調(diào)用 scoket netty -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.7</version>
</dependency>
3.工具類封裝 --- HttpClientUtils
public class HttpClientUtils {
/**
* http請(qǐng)求工具類荡短,post請(qǐng)求
*
* @param url
* url
* @param params
* json字符串的參數(shù)
* @return
* @throws Exception
*/
public static String httpPost(String url, String params) throws Exception {
// 創(chuàng)建httpClient對(duì)象
DefaultHttpClient defaultHttpClient = null;
try {
defaultHttpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/json;charset=ut-8");
if (params != null) {
System.out.println("請(qǐng)求參數(shù):" + params);
// 設(shè)置請(qǐng)求參數(shù)
HttpEntity httpEntity = new StringEntity(params, "utf-8");
httpPost.setEntity(httpEntity);
}
// 執(zhí)行post請(qǐng)求,并得到相應(yīng)結(jié)果
HttpResponse httpResponse = defaultHttpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() != 200) {
String errorLog = "請(qǐng)求失敗哆键,errorCode:" + httpResponse.getStatusLine().getStatusCode();
throw new Exception(url + errorLog);
}
// 解析結(jié)果
HttpEntity responseEntity = httpResponse.getEntity();
String responseStr = EntityUtils.toString(responseEntity, "utf-8");
System.out.println("請(qǐng)求結(jié)果:" + responseStr);
return responseStr;
} catch (ClientProtocolException e) {
e.printStackTrace();
throw e;
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
if (defaultHttpClient != null)
defaultHttpClient.getConnectionManager().shutdown();
}
}
/**
* http請(qǐng)求工具類掘托,get請(qǐng)求
*
* @param url
* 請(qǐng)求地址:可以已經(jīng)帶參數(shù)(?),也可以沒有帶參數(shù)籍嘹,在params中傳過來
* @param params
* 參數(shù):值支持字符串和list
* @return
* @throws Exception
*/
public static String httpGet(String url, Map<String, Object> params) throws Exception {
DefaultHttpClient defaultHttpClient = null;
try {
defaultHttpClient = new DefaultHttpClient();
if (params != null) {
// 參數(shù)的拼接
StringBuilder stringBuilder = new StringBuilder();
Iterator<String> iterator = params.keySet().iterator();
String key;
while (iterator.hasNext()) {
key = iterator.next();
Object val = params.get(key);
if (val instanceof List) {
// 如果是list闪盔,則遍歷拼接
List v = (List) val;
for (Object o : v) {
stringBuilder.append(key).append("=").append(o.toString()).append("&");
}
} else {
// 字符串:直接拼接
stringBuilder.append(key).append("=").append(val.toString()).append("&");
}
}
// 刪除最后一個(gè)&
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
if (url.indexOf("?") > 0) {
// url地址本身包含?
url = url + "&" + stringBuilder.toString();
} else {
url = url + "?" + stringBuilder.toString();
}
}
System.out.println("請(qǐng)求地址:"+url);
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Content-Type", "application/json;charset=ut-8");
// 執(zhí)行
HttpResponse httpResponse = defaultHttpClient.execute(httpGet);
if (httpResponse.getStatusLine().getStatusCode() != 200) {
String errorLog = "請(qǐng)求失敗辱士,errorCode:" + httpResponse.getStatusLine().getStatusCode();
throw new Exception(url + errorLog);
}
// 解析結(jié)果
HttpEntity responseEntity = httpResponse.getEntity();
String responseStr = EntityUtils.toString(responseEntity, "utf-8");
System.out.println("請(qǐng)求結(jié)果:" + responseStr);
return responseStr;
} catch (ClientProtocolException e) {
e.printStackTrace();
throw e;
} catch (IOException e) {
e.printStackTrace();
throw e;
} finally {
if (defaultHttpClient != null)
defaultHttpClient.getConnectionManager().shutdown();
}
}
4.常量封裝
public class WxConstants {
public final static String APPID = "wxd853562a0548a7d0";
//用戶授權(quán)后微信的回調(diào)域名
public final static String CALLBACK="http://bugtracker.itsource.cn";
public final static String SCOPE = "snsapi_login";
public final static String APPSECRET = "4a5d5615f93f24bdba2ba8534642dbb6";
//微信上獲取code的地址
public final static String CODEURL = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
//微信上獲取at的地址
public final static String ACCESSTOKEURL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
//微信上獲取用戶信息的地址
public final static String USERINFOURL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
}
5.Controller
@Controller
public class CoreController {
/**
* ①:用戶進(jìn)入登錄頁面:
* 目的是組裝訪問授權(quán)地址(拉起微信二維碼)
* @return
*/
@RequestMapping("/login")
public String login(Model model) {
System.out.println("99999999999999999");
String redirect_uri="";
try {
redirect_uri = URLEncoder.encode(WxConstants.CALLBACK, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} ;
String codeUrl = WxConstants.CODEURL.replace("APPID",WxConstants.APPID).replace("REDIRECT_URI",redirect_uri).replace("SCOPE",WxConstants.SCOPE);
model.addAttribute("authUrl", codeUrl);
return "forward:/login.jsp";
}
/**
* ②:微信重定向到應(yīng)用設(shè)置的回調(diào)地址:
* 用戶確認(rèn)后進(jìn)入這個(gè)回調(diào)地址:
* 通過code獲取at泪掀;
* 通過at獲取用戶信息
* 回到主頁面進(jìn)行用戶信息顯示
* @param code
* @param state
* @param model
* @return
* @throws Exception
*/
@RequestMapping("/callBack")
public String callBack(Model model,String code,String state) throws Exception{
System.out.println("code="+code);
System.out.println("state="+state);
// 獲取到code和state
if (!StringUtils.isEmpty(code) && !StringUtils.isEmpty(state)) {
// 1.通過code獲取access_token
String url = WxConstants.ACCESSTOKEURL.replace("APPID", WxConstants.APPID)
.replace("SECRET", WxConstants.APPSECRET).replace("CODE", code);
String tokenInfoStr = HttpClientUtils.httpGet(url, null);
// 應(yīng)該做at的持久化操作
System.out.println("用戶token信息:" + tokenInfoStr);
JSONObject tokenInfoObject = (JSONObject) JSON.parse(tokenInfoStr);
// 2.通過access_token和openid獲取用戶信息
String userInfoUrl = WxConstants.USERINFOURL.replace("ACCESS_TOKEN", tokenInfoObject.getString("access_token"))
.replace("OPENID", tokenInfoObject.getString("openid"));
//獲取到的用戶信息
String userInfoStr = HttpClientUtils.httpGet(userInfoUrl, null);
System.out.println("用戶信息:userInfoStr:" + userInfoStr);
model.addAttribute("tokenInfoObject", tokenInfoObject);
model.addAttribute("userInfoObject", userInfoStr);
//用戶信息的值:
JSONObject userInfoJson = (JSONObject) JSON.parse(userInfoStr);
Object headimgurl = userInfoJson.get("headimgurl");
Object nickname = userInfoJson.get("nickname");
//獲取用戶信息:應(yīng)該做持久化,并做自己系統(tǒng)的登錄邏輯判斷颂碘,跳轉(zhuǎn)到主頁
model.addAttribute("headimgurl", headimgurl);
model.addAttribute("nickname", nickname);
}
return "forward:/main.jsp";
}
2.準(zhǔn)備頁面(這里演示個(gè)簡單的)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="/wechat/login1">微信登錄</a>
</body>
</html>
3.新建WeChatController
4.新建
<%--引入微信的js支持--%>
<script type="text/javascript" src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<script type="text/javascript">
var obj = new WxLogin({
self_redirect:true,
id:"login_container",
appid: "wxd853562a0548a7d0",
scope: "snsapi_login",
redirect_uri: "http://bugtracker.itsource.cn/wechat/callback",
state: "xxx",
style: "white",
href: ""
});
</script>
7.WeChatController
建新表
1.針對(duì)返回的字段建新表异赫。。要加url_id的外建。關(guān)聯(lián)起來
2.根據(jù)openid查詢數(shù)據(jù)庫
3.如果沒有查到
??????????java育兒園里的小學(xué)生“磨陀貨”友情提供KJ笾ぁ!
??????????請(qǐng)大家尊重原創(chuàng)靠抑,如要轉(zhuǎn)載量九,請(qǐng)注明出處:
??????????轉(zhuǎn)載自:http://www.reibang.com/p/161b4e657a4d,謝謝T熊娩鹉!
??????????有任何疑問,歡迎加入Java交流群458443587(加群時(shí)請(qǐng)備注)