微信第三方登陸先後端分離實現思路

微信第三方登陸先後端分離實現思路

前端實現

這裏說一下先後端的思路,頁面加載時聲明一個變量state='時間戳+6位隨機數', 前端路徑生成二維碼, 其中有個state參數須要咱們傳遞,這個參數你傳什麼,微信回調的時候就會給你返回什麼。 咱們用以前生成那個state,當用戶點擊微信登陸的按鈕,咱們就經過以state值爲key和後端進行websocket鏈接,同時彈出二維碼頁面。 state對前端來講就至關於一個令牌,告訴後端是誰在使用微信登陸。目的在於,當後臺收到回調的時候,能準確的把數據返回當前掃碼的用戶, 後臺在微信回調的時候能拿到code的值和state的值,經過code去拿access_tokenopenid , 經過這兩個值去請求微信用戶最新信息, 後端定義好返回的狀態值表明啥,無非兩種狀態碼:1.已經綁定:取出user信息, 經過websocket返回給前端,2.沒綁定:返回微信帳戶的openid和頭像暱稱。 前端收到後端發送的websocket信息,判斷微信綁定狀態,若是綁定路由跳轉到登陸完成頁面,若是未綁定,跳轉到綁定或註冊頁面。javascript

第一步

前端先設置好生成二維碼的路徑,前端

this.url =
      "https://open.weixin.qq.com/connect/qrconnect?appid=" +
      this.appid +
      "&redirect_uri=" +
      this.redirect_uri +
      "&response_type=code&scope=snsapi_login&state=" +
      this.state +
      "#wechat_redirect";

複製代碼

參數解釋(這裏直解釋須要修改的參數)

參數名 備註
appid 這個就是申請微信登陸應用的appid
redirect_uri 微信的回調地址,記得這裏要url轉碼
state 這個是微信給咱們本身傳遞的參數,無論你傳的是啥,都會在回調中給你返回回來

第二步

用戶點擊微信登陸頁面,和後端進行websocket鏈接,鏈接的key就是咱們生產二維碼鏈接中的statejava

let wsname = "ws://www.niezhiliang.com:8086/socketServer/" + this.state;
      this.ws = new WebSocket(wsname);
      //鏈接成功觸發
      this.ws.onopen = function(evt) {
      };
      //這個是接收後臺發送信息的方法
      this.ws.onmessage = function(evt) {
        var data = JSON.parse(evt.data);
        console.log(data)
       //在這裏判斷後臺給的狀態是1仍是2 並進行相應的操做
      })

複製代碼

而後再彈出二維碼頁面(居中顯示)git

//this.url=咱們在頁面加載的時候拼接好的
WxLogin() {
      this.itop = (window.screen.availHeight - 500) / 2;
      //得到窗口的水平位置
      this.ileft = (window.screen.availWidth - 400) / 2;
      this.w = window.open(
        this.url,
        "newwindow",
        "height=500, width=400, top=" +
          this.itop +
          ", left = " +
          this.ileft +
          ", toolbar=no, menubar=no,scrollbars=no, resizable=no,location=no, status=no"
      );
    }
複製代碼

後端Java實現(websocket就不解釋啦,若是不懂能夠去看個人另外一個項目)

github.com/niezhiliang…github

第一步

這邊是websocket的代碼web

  • 配置websocket鏈接服務
@ServerEndpoint(value = "/socketServer/{userid}")
@Component
public class SocketServer {

	private Session session;
	private static Map<String,Session> sessionPool = new HashMap<String,Session>();
	private static Map<String,String> sessionIds = new HashMap<String,String>();

	/** * 用戶鏈接時觸發 * @param session * @param userid */
	@OnOpen
	public void open(Session session,@PathParam(value="userid")String userid){
		this.session = session;
		sessionPool.put(userid, session);
		sessionIds.put(session.getId(), userid);
	}

	/** * 收到信息時觸發 * @param message */
	@OnMessage
	public void onMessage(String message){
		System.out.println("當前發送人sessionid爲"+session.getId()+"發送內容爲"+message);
	}

	/** * 鏈接關閉觸發 */
	@OnClose
	public void onClose(){
		sessionPool.remove(sessionIds.get(session.getId()));
		sessionIds.remove(session.getId());
	}

	/** * 發生錯誤時觸發 * @param session * @param error */
    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

	/** *信息發送的方法 * @param message * @param userId */
	public static void sendMessage(String message,String userId){
		Session s = sessionPool.get(userId);
		if(s!=null){
			try {
				s.getBasicRemote().sendText(message);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
}
複製代碼
  • 提供給前端發送信息的api
@RequestMapping(value = "/sendpost")
    public String sendPost(@RequestBody Params params) {
        if (params.getJson() == null || params.getUserid() == null) {
            return "error";
        }
        logger.info(params.getJson()+"-----------"+params.getUserid());
        SocketServer.sendMessage(params.getJson(),params.getUserid());
        return "success";
    }
複製代碼

第二步

這邊是微信回調代碼spring

/** * 微信掃碼回調 * @return */
    @RequestMapping(value = "/callback")
    public void callBack(Device device) {
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        RespInfo respInfo = new RespInfo();
        respInfo.setStatus(InfoCode.ERROR);
        if (code != null) {
            StringBuffer url = new StringBuffer();
            /*********獲取token************/
            url.append(request_url)
                    .append("appid=")
                    .append(appid)
                    .append("&secret=")
                    .append(secret)
                    .append("&code=")
                    .append(code)
                    .append("&grant_type=")
                    .append(grant_type);
            logger.info(url.toString());
			 //調用微信查詢用戶基本信息的api方法
            JSONObject jsonObject =
                    JSON.parseObject(HttpUtil.getResult(url.toString()));
            //拿到openid和請求微信api使用的token
            String openid =jsonObject.get("openid").toString();
            String token = jsonObject.get("access_token").toString();

            /*********獲取userinfo************/
            url = new StringBuffer();
            url.append(userinfo_url)
                    .append("access_token=")
                    .append(token)
                    .append("&openid=")
                    .append(openid);
            logger.info(url.toString());
            //經過上面拿到的token和openid獲取用戶的基本信息
            String result = HttpUtil.getResult(url.toString());
            WeixinInfo weixinInfo = JSON.parseObject(result,WeixinInfo.class);
            if (weixinInfo != null) {
               //這個方法是爲了去除微信暱稱的特殊符號,爲了不保存數據庫操做報異常我把全部的暱稱表情都替換成了*
                weixinInfo.setNickname(filterEmoji(weixinInfo.getNickname()));
                //插入數據庫操做
                weiXinService.insertOrUpdateSelective(weixinInfo);
            }
            //經過openid去找用戶是否綁定
            User user = userService.getByOpenId(openid);
            if (user == null) {//說明該微信未綁定任何帳號
                respInfo.setStatus(InfoCode.INVALID_TOKEN);
                respInfo.setMessage("請先註冊再進行微信綁登陸操做");
                Map<String,Object> map = new HashMap<String,Object>();
                map.put("openid",openid);
                map.put("headimgurl",weixinInfo.getHeadimgurl());
                map.put("nickname",weixinInfo.getNickname());
                respInfo.setContent(map);
            } else {//這裏是表示該微信已經綁定了用戶帳號,直接返回用戶登陸信息就好
                respInfo.setStatus(InfoCode.SUCCESS);
                respInfo.setContent(user);
            }
        }
        String json = JSON.toJSONString(respInfo);
        /************websocket將數據響應給前端**************/
        Map map = new HashMap();
        map.put("userid",state);
        map.put("json",json);
        String params = JSON.toJSONString(map);
        try {
            //這裏是將結果經過websocket返回給前端 
            System.out.println(HttpUtil.
	    doPost(「http://www.niezhiliang.com:8086/websocket/sendpost」,params));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
複製代碼
相關文章
相關標籤/搜索