专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

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

ins518 2024-09-18 17:44:07 技术文章 13 ℃ 0 评论

这里说一下前后端的思路,页面加载时声明一个变量state ='时间戳+6位随机数', 前端路径生成二维码, 其中有个state 参数需要我们传递,这个参数你传什么,微信回调的时候就会给你返回什么。 我们用之前生成那个state,当用户点击微信登录的按钮,我们就通过以state值为key和后端进行websocket连接,同时弹出二维码页面。 state对前端来说就相当于一个令牌,告诉后端是谁在使用微信登录。目的在于,当后台收到回调的时候,能准确的把数据返回当前扫码的用户, 后台在微信回调的时候能拿到code 的值和state 的值,通过code 去拿access_token 和openid , 通过这两个值去请求微信用户最新信息, 后端定义好返回的状态值代表啥,无非两种状态码: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";
复制代码

参数解释(这里直解释需要修改的参数)

第二步

用户点击微信登录页面,和后端进行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();
 }
 }
复制代码

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表