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

来源:互联网 发布:粤贵银模拟软件下载 编辑:程序博客网 时间:2024/06/05 01:20

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

首先说明一下微信网页授权的机制,你的网页授权入口应该是类似“https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxbdeafce2a5d59561&redirect_uri=https%3a%2f%2fsaima.bidongtu.cn%2frenzheng&response_type=code&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=code&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=code&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")@ResponseBodypublic 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 blocke.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获取用户信息时的跨域问题了

原创粉丝点击