微信第三方登录前后端分离实现思路

微信第三方登录前后端分离实现思路

前端实现

这里说一下前后端的思路,页面加载时声明一个变量state='时间戳+6位随机数', 前端路径生成二维码, 其中有个state参数需要我们传递,这个参数你传什么,微信回调的时候就会给你返回什么。 我们用之前生成那个state,当用户点击微信登录的按钮,我们就通过以state值为key和后端进行websocket连接,同时弹出二维码页面。 state对前端来说就相当于一个令牌,告诉后端是谁在使用微信登录。目的在于,当后台收到回调的时候,能准确的把数据返回当前扫码的用户, 后台在微信回调的时候能拿到code的值和state的值,通过code去拿access_tokenopenid , 通过这两个值去请求微信用户最新信息, 后端定义好返回的状态值代表啥,无非两种状态码:1.已经绑定:取出user信息, 通过websocket返回给前端,2.没绑定:返回微信账户的openid和头像昵称。 前端收到后端发送的websocket信息,判断微信绑定状态,如果绑定路由跳转到登录完成页面,如果未绑定,跳转到绑定或注册页面。

第一步

前端先设置好生成二维码的路径,

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就是我们生产二维码连接中的state

 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  并进行相应的操作
      })

复制代码

然后再弹出二维码页面(居中显示)

//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…

第一步

这边是websocket的代码

  • 配置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";
    }
复制代码

第二步

这边是微信回调代码

 /**
     * 微信扫码回调
     * @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();
        }
    }
复制代码

猜你喜欢

转载自juejin.im/post/5d5e7febf265da03b8106699