解决微信网页授权跨域问题

最近在做一个微信网页版的小游戏,在获取用户数据的时候遇到了跨域的问题。

首先说明一下微信网页授权的机制,你的网页授权入口应该是类 似“https://open.weixin.qq.com/connect/oauth2/authorize? appid=wxbdeafce2a5d59561&redirect_uri=https%3a%2f%2fsaima.bidongtu.cn%2frenzheng&response_type=co de&scope=snsapi_userinfo&state=123#wechat_redirect”的地址,其中redirect_uri后面应该为你后台的解密的接口口地址。当你请求这个地址时,会先向微信服务器请求授权并获取code,获取code成功后在根据redirect_uri路径去请求你的后台服务器,后台服务器根据code去微信服务器获取用户的信息然后返回给前端页面。

可是在实际开发过程中遇到了跨域的问题,我最开始是这样想的,首先写一个页面,在这个页面加载的时候发送“https://open.weixin.qq.com/connect/oauth2/authorize? appid=wxbdeafce2a5d59561&redirect_uri=https%3a%2f%2fsaima.bidongtu.cn%2frenzheng&response_type=co de&scope=snsapi_userinfo&state=123#wechat_redirect”的ajax请求,获取用户的信息,(/renzheng为后台解密借口地址)。可是这样做后台能获取到用户信息,但是不能讲信息传送给前端页面,因为存在跨域问题。后来咨询了一下朋友,得到这样一个解决方案。

首先在redirect_uri路径里面直接请求静态页面,也就是这样“https://open.weixin.qq.com/connect/oauth2/authorize? appid=wxbdeafce2a5d59561&redirect_uri=https%3a%2f%2fsaima.bidongtu.cn%2findex.html&response_type=co de&scope=snsapi_userinfo&state=123#wechat_redirect”的地址,微信服务器会获取code然后去访问你的后端服务器获取index.html静态页面返回给前端。此时在前端页面里面可以从当前的地址信息里面获取code,然后直接向你的后端服务器解密端口发送请求,此时就不存在跨域问题。具体代码如下:

在index.html页面解析地址获取code代码:

function getopenId() {
		var userData = null;
		userData = JSON.parse(localStorage.getItem('user'));
		if(userData) {
			return userData;
		} else {
			var getQueryString = function(name) {
				var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
				var r = window.location.search.substr(1).match(reg);
				if(r != null) return unescape(r[2]);
				return null;
			};
			var code = getQueryString('code');
			if(code) {
				$.ajax({
					type: "get",
					url: "https://saima.bidongtu.cn/renzheng.do",
					data: {
						code: code
					},
					async: false,
					success: function(d) {
						console.log(d)
						userData = d;
					},
					error: function(data) {
						alert('网络错误');
					}
				});
			} else {
				alert('请从微信公众号打开');
			}
			localStorage.setItem('user', JSON.stringify(userData));
			return userData;
		}
后端的解密授权接口如下:
	@RequestMapping("/renzheng.do")
	@ResponseBody
	public Object authMehtod(String code){
		System.out.println("code:"+code);
		String jsonText ="";
		StringBuffer url=new StringBuffer("https://api.weixin.qq.com/sns/oauth2/access_token?");
		url.append("appid=").append("wxbdeafce2a5d59561").append("&");
		url.append("secret=").append("ba37510578b839ca754e18f41cee4518").append("&");
		url.append("code=").append(code).append("&");
		url.append("grant_type=").append("authorization_code");
		System.out.println("url:"+url);
		jsonText= Tools.getStaticString(url.toString());
		System.out.println("jsonText:"+jsonText);
		WeixinBackInfo weixinBackInfo =null;
		try {
			weixinBackInfo = mapper.readValue(jsonText, WeixinBackInfo.class);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			Map<String,String> map=new HashMap<>();
			map.put("error","解密失败");
			return map;
		}
		System.out.println("openId:"+weixinBackInfo.getOpenid());
		UserInfo userInfo = new UserInfo();
		if(weixinBackInfo.getErrcode()==null){
			try {
				userInfo=getUserInfo(weixinBackInfo);
			} catch (Exception e) {
				e.printStackTrace();
				Map<String,String> map=new HashMap<>();
				map.put("error","解密失败");
				return map;
			}
		}
		if(userInfo.getOpenid()!=null){
			UserDTO userDTO=userService.findUser(userInfo.getOpenid());
			if(userDTO==null){//如果数据库没有此人信息,将此人存入数据库
				userService.addUser(userInfo.getOpenid(),userInfo.getHeadimgurl());
			}
		}
		return userInfo;
	}
	public UserInfo getUserInfo(WeixinBackInfo backInfo) throws Exception {
		StringBuffer url = new StringBuffer("https://api.weixin.qq.com/sns/userinfo?");
		String jsonText ="";
		url.append("access_token=").append(backInfo.getAccess_token()).append("&");
		url.append("openid=").append(backInfo.getOpenid()).append("&");
		url.append("lang=en");
		System.out.println("UserInfo_Url:"+url);
		jsonText=Tools.getStaticString(url.toString());
		String str="";
		str=new String(jsonText.getBytes("ISO-8859-1"),"UTF-8");
		System.out.println("UserInfo_Url:"+str);
		UserInfo userInfo =null;
		userInfo = mapper.readValue(str, UserInfo.class);
		return userInfo;
	}
所用到的实体类以及工具:

用户类UserInfo:

public class UserInfo {
	private String language;
	private String openid;
	private String nickname;
	private String sex;
	private String province;
	private String city;
	private String country;
	private String headimgurl;
	private List<String> privilege;
	
	public String getOpenid() {
		return openid;
	}
	public void setOpenid(String openid) {
		this.openid = openid;
	}

	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getProvince() {
		return province;
	}
	public void setProvince(String province) {
		this.province = province;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
	public String getHeadimgurl() {
		return headimgurl;
	}
	public void setHeadimgurl(String headimgurl) {
		this.headimgurl = headimgurl;
	}
	public List<String> getPrivilege() {
		return privilege;
	}
	public void setPrivilege(List<String> privilege) {
		this.privilege = privilege;
	}
	public String getUnionid() {
		return unionid;
	}
	public void setUnionid(String unionid) {
		this.unionid = unionid;
	}
	public String getNickname() {
		return nickname;
	}
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	public String getLanguage() {
		return language;
	}
	public void setLanguage(String language) {
		this.language = language;
	}
	private String unionid;
}
微信服务器返回的JSON解析后的实体类WeixinBackInfo
public class WeixinBackInfo {
	private String access_token;
	private String expires_in;
	private String refresh_token;
	private String openid;
	private String scope;
	private String errcode;
	private String errmsg;
	
	
	public String getAccess_token() {
		return access_token;
	}
	public void setAccess_token(String access_token) {
		this.access_token = access_token;
	}
	public String getExpires_in() {
		return expires_in;
	}
	public void setExpires_in(String expires_in) {
		this.expires_in = expires_in;
	}
	public String getRefresh_token() {
		return refresh_token;
	}
	public void setRefresh_token(String refresh_token) {
		this.refresh_token = refresh_token;
	}
	public String getOpenid() {
		return openid;
	}
	public void setOpenid(String openid) {
		this.openid = openid;
	}
	public String getScope() {
		return scope;
	}
	public void setScope(String scope) {
		this.scope = scope;
	}
	public String getErrcode() {
		return errcode;
	}
	public void setErrcode(String errcode) {
		this.errcode = errcode;
	}
	public String getErrmsg() {
		return errmsg;
	}
	public void setErrmsg(String errmsg) {
		this.errmsg = errmsg;
	}
}
java后台向微信服务器发送请求的工具类Tools
public class Tools {
	private static HttpClient client;  
    private static GetMethod getMethod;  
    static {  
        client = new HttpClient();  
    }  
    public static String getStaticString(String URL){
    	 getMethod = new GetMethod(URL); 
    	 String jsonText="";
    	 try {  
             int status = client.executeMethod(getMethod);  
             if (status == HttpStatus.SC_OK) {// HTTP 200 OK  
                 jsonText = getMethod.getResponseBodyAsString(); 
             }  
         } catch (Exception e) {  
             System.err.println(e);  
         }  
    	 return jsonText;
    }
}
该工具类需要用到commons-httpclient包,请导入依赖

	<dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
如上就能解决用ajax获取用户信息时的跨域问题了

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值