第三方登錄,首先需要設計擴展性的表結構。參照如下:本文主要寫第三方登錄的代碼。
淺談數據庫用戶設計:http://www.cnblogs.com/jiqing9006/p/5937733.html
可綁定可擴展的賬號系統:http://blog.cocosdever.com/2016/03/08/The-design-principle-and-implementation-of-extensible-account-system-1/
第三方登錄流程是:先獲取code---->然后獲取access_token----->根據token獲取用戶信息。
前台頁面實現步驟:點擊微博登錄按鈕---->打開一個子窗口,進行授權------>授權完成,跳轉到首頁或上次瀏覽的頁面。
1、寫第三方登錄的按鈕,點擊按鈕時,打開一個子窗口。
redirect_uri是你在微博上設置的回調地址。
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <script type="text/javascript" src="http://statics.2cto.com/js/jquery.min.js"></script> </head> <script type="text/javascript"> var qqAuthWin,weiboAuthWin; /** * 關閉QQ子窗口 */ function closeQQWin(){ var result = $("#qq").val(); if(result != ""){ console.log(result); qqAuthWin.close(); }else{ console.log("值為空"); } } /** * QQ登錄 * http://localhost:9090/logback/qq.jsp QQ互聯上設置的回調地址 */ function loginQQ(){ qqAuthWin = window.open("https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=CLIENT_ID&state=register&redirect_uri=http://localhost:9090/logback/qq.jsp", 'QQ授權登錄','width=770,height=600,menubar=0,scrollbars=1,'+ 'resizable=1,status=1,titlebar=0,toolbar=0,location=1'); } /** * 關閉微博子窗口 */ function closeWeiboWin(){ var result = $("#weibo").val(); if(result != ""){ console.log(result); weiboAuthWin.close(); }else{ console.log("值為空"); } } /** * 微博登錄 * http://localhost:9090/logback/weibo.jsp這個就是在微博上設置的回調地址 */ function loginWeibo(){ weiboAuthWin = window.open("https://api.weibo.com/oauth2/authorize?client_id=CLIENT_ID&response_type=code&state=register&redirect_uri=http://localhost:9090/logback/weibo.jsp", '微博授權登錄','width=770,height=600,menubar=0,scrollbars=1,'+ 'resizable=1,status=1,titlebar=0,toolbar=0,location=1'); } </script> <body> <input type="hidden" id="qq" value=""> <a href="#" onClick="loginQQ()">QQ登錄</a> <br><br> <hr> <br> <input type="hidden" id="weibo" value=""> <a href="#" onClick="loginWeibo()">微博登錄</a> </body> </html>
2、回調地址頁(qq.jsp、weibo.jsp)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; String code = request.getParameter("code");//獲取QQ返回的code String state = request.getParameter("state"); %> <!DOCTYPE HTML> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'weibo.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <script type="text/javascript" src="http://statics.2cto.com/js/jquery.min.js"></script> <script> $(function(){ var code = "<%=code%>"; var state = "<%=state%>"; $.ajax({ url:"http://localhost:8080/cms_manage/api/qqLogin", type:"post", data:{code:code,state:state}, dataType:"json", success:function(result){ result = JSON.stringify(result); console.log(result); //把返回的數據傳給父窗口的隱藏域中 window.opener.document.getElementById("qq").value = result; //授權完成后,關閉子窗口 window.opener.closeQQWin(); } }); }); </script> </head> <body> 登錄成功。 </body> </html>
qq.jsp和weibo,jsp是一樣的。。。
3、java代碼
/** * 微博第三方登錄 * @author techbuddy * */ @Controller public class WeiboLoginController { private Logger logger = Logger.getLogger(WeiboLoginController.class); private final static String CLIENT_ID = ""; private final static String CLIENT_SERCRET = ""; private final static String GET_TOKEN_URL = "https://api.weibo.com/oauth2/access_token"; private final static String REDIRECT_URI = "http://localhost:9090/logback/weibo.jsp"; private final static String GET_USER_INFO = "https://api.weibo.com/2/users/show.json"; private final static String GET_TOKEN_INFO_URL = "https://api.weibo.com/oauth2/get_token_info"; private final static String STATE = "register"; @RequestMapping(value="/api/weiboLogin",method=RequestMethod.POST) @ResponseBody public CMS_Result weiboLogin(HttpServletRequest request,HttpServletResponse response){ CMS_Result result = null; String error_code = request.getParameter("error_code"); if(StringUtils.isNotBlank(error_code)){ result = CMS_Result.bulid("5001", "微博授權失敗"); }else{ try{ //獲取code String code = request.getParameter("code"); logger.info("code:" + code); //獲取state String state = request.getParameter("state"); logger.info("state:"+state); String access_token = ""; String expires_in = ""; String uid = ""; if(STATE.equals(state)){ //獲取token JSONObject token = getAccessToken(code); access_token = token.getString("access_token"); uid = token.getString("uid"); expires_in = String.valueOf(token.getInt("expires_in")); logger.info("token:"+token); }else{ result = CMS_Result.bulid("5001", "微博授權失敗"); } //查詢該用戶信息 OauthUser oauthUser = oauthUserService.findWeiboByIdentifier(uid); Master master = null; if(oauthUser != null){ master = masterInfoDao.findById(oauthUser.getMaster_id()); }else{ //獲取用戶信息 JSONObject userInfo = getUserInfo(access_token, uid); logger.info("用戶信息"+userInfo); String nickname = userInfo.getString("screen_name"); String profile_image_url = userInfo.getString("profile_image_url"); String gender = "f".equals(userInfo.getString("gender"))?"1":"0"; //向第三方登錄表中添加數據 OauthUser user = new OauthUser(); user.setId(UUID.randomUUID().toString()); String master_id = UUID.randomUUID().toString(); user.setMaster_id(master_id); user.setIdentity_type("weibo"); user.setIdentifier(uid); user.setCredential(access_token); user.setExpires_in(expires_in); user.setStatus("0"); oauthUserService.insert(user); //向用戶表中添加默認數據 Master masterUser = new Master(); masterUser.setId(master_id); masterUser.setNickname(nickname); masterUser.setHead_portrait(profile_image_url); masterUser.setSex(gender); //由於第三方登錄沒有用戶名密碼,而且該字段在數據庫中不為空,在此設置默認用戶名密碼 masterUser.setUser_name("wbu"+access_token.substring(0, 9)); masterUser.setPassword("wbp"+access_token.substring(0, 9)); masterInfoService.insertDefault(masterUser); master = masterUser; } result = CMS_Result.ok(); }catch (Exception e) { e.printStackTrace(); result = CMS_Result.bulid("5001", "登錄失敗"); } } return result; } /** * 獲取AccessToken */ private JSONObject getAccessToken(String code) { StringBuilder sb = new StringBuilder(); sb.append("grant_type=authorization_code"); sb.append("&client_id=" + CLIENT_ID); sb.append("&client_secret=" + CLIENT_SERCRET); sb.append("&redirect_uri=" + REDIRECT_URI); sb.append("&code=" + code); String result = HttpsUtil.post(GET_TOKEN_URL,sb.toString()); /** * 返回數據 * { * "access_token": "ACCESS_TOKEN", * "expires_in": 1234, * "remind_in":"798114", * "uid":"12341234" * } */ JSONObject json = new JSONObject(result); return json; } /** * 獲取用戶信息 * @param access_token * @param uid 查詢的用戶ID * @return */ private JSONObject getUserInfo(String access_token,String uid){ StringBuilder sb = new StringBuilder(); sb.append("?access_token=" + access_token); sb.append("&uid=" + uid); String result = HttpsUtil.get(GET_USER_INFO+sb.toString()); //返回參數:查看http://open.weibo.com/wiki/2/users/show JSONObject json = new JSONObject(result); return json; }