微信扫码登录只能填一个授权回调域问题

背景

公司增加了个微信扫码登录,费劲千辛万苦终于把应用申请下来了,但遇到了一个头疼的事情:微信授权回调域只能写一个,且不支持通配。这下可好了,总不能把每个需要微信登录的二级域名都申请一个应用吧?而且一个开放平台账号最多申请十个。

使用html重定向

这种方法网上一大堆,大体思想是,微信授权回调域写一个域名,然后将一个html页面放到这个域名下,微信扫码登录时填写的redirect_url就是到这个html,然后在这个html的js代码中,根据某一个参数去判断当前路由应该重定向到哪个地址。

html重定向做法

假如我们有多个地址需要做微信扫码登录,比如我们的研发环境,测试环境,生产环境都需要做微信扫码登陆,但又不想给研发测试环境做外网的端口映射,那么可以使用这种方式。
首先在开放平台的授权回调域中写一个公共授权域名,比如oauth.loooswc.cn
微信扫码登录只能填一个授权回调域问题_第1张图片
然后将get-wechat-code.html页面放到该域名下,比如oauth.loooswc.cn/oauth/wechat/get-wechat-code.html
最后在调用微信获取code请求时,redirect_url就写oauth.loooswc.cn/oauth/wechat/get-wechat-code.html?env={env}&request=/oauth/wechat/login_callback.do,通过js代码根据参数env去判断应该重定向到哪个地址,比如env=dev时,则重定向到http://localhost:4200/oauth/wechat/login_callback.do
但是这种办法有种缺点,就是会将研发测试环境的地址暴漏出去,而且这个地址对生产环境是没有任何意义的,虽然别人拿到这个内网地址也访问不通,但总归是不好的,所以我们可以使用下面这种方法,通过后台请求重定向。
附带get-wechat-code.html代码


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>微信登陆title>
head>
<body>
<script>
    function getUrlParams(key) {
        var args = {};
        var pairs = location.search.substring(1).split('&');
        for (var i = 0; i < pairs.length; i++) {
            var pos = pairs[i].indexOf('=');
            if (pos === -1) {
                continue;
            }
            args[pairs[i].substring(0, pos)] = decodeURIComponent(pairs[i].substring(pos + 1));
        }
        return args[key];
    }
    function getRealRedirectUrl(env){
        var realRedirectUrl = 'https://admin.loooswc.cn/';
        if('dev' == env){
            realRedirectUrl = 'http://localhost:8080/';
        }else if('test' == env){
            realRedirectUrl = 'http://192.168.1.10:30080/';
        }else if('pre-prod' == env){
            realRedirectUrl = 'http://192.168.1.20:30080/';
        }

        return realRedirectUrl;
    }
    function appendParams(params, url) {
        var baseWithSearch = url.split('#')[0];
        var hash = url.split('#')[1];
        for (var i = 0; i < params.length; i++) {
            if (params[i].value !== undefined) {
                var newParam = params[i].key + "=" + params[i].value;
                if (baseWithSearch.indexOf('?') > 0) {
                    var oldParamReg = new RegExp(params[i].key + '=[-\\w]{0,40}', 'g');
                    if (oldParamReg.test(baseWithSearch)) {
                        baseWithSearch = baseWithSearch.replace(oldParamReg, newParam);
                    } else {
                        baseWithSearch += "&" + newParam;
                    }
                } else {
                    baseWithSearch += "?" + newParam;
                }
            }
        }
        if (hash) {
            url = baseWithSearch + '#' + hash;
        } else {
            url = baseWithSearch;
        }
        return url;
    }
    var code = getUrlParams('code');
    var appId = getUrlParams('appid');
    var scope = getUrlParams('scope') || 'snsapi_base';
    var state = getUrlParams('state');
    var env = getUrlParams('env');
    var request = getUrlParams('request');
    var redirectUrl;
    if (!code) {
        redirectUrl = appendParams([{
            key: 'appid',
            value: appId
    }, {
            key: 'redirect_uri',
            value: encodeURIComponent(location.href)
        }, {
            key: 'response_type',
            value: 'code'
        }, {
            key: 'scope',
            value: scope
        }, {
            key: 'state',
            value: state
        }], 'https://open.weixin.qq.com/connect/oauth2/authorize#wechat_redirect');
            } else {
        redirectUrl = appendParams([{key: 'code', value: code},{
            key: 'state',
            value: state
        }], getRealRedirectUrl(env) + request);
    }
   location.href = redirectUrl;
   // window.close();
script>
body>
html>

通过后台请求重定向

大体流程是,在某一个部署了后台服务的代码中,增加一个Controller接口,该接口通过参数中的env和request,将请求重定向到{env}+{request}接口中,同时附带上自定义和微信回调携带的code和state参数,从而达到转发请求的作用。

后台请求重定向做法

在后台程序中,增加一个Controller接口

@Controller
@RequestMapping("/oauth/wechat")
public class OauthWechatController {
	private static final Logger log = LoggerFactory.getLogger(OauthWechatController.class);

	@Autowired
	private OauthWechatConfiguration oauthWechatConfiguration;

	@RequestMapping(value= "/redirect" , method = RequestMethod.GET)
	@ResponseBody
	public void  redirect(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String requestUrl = request.getParameter("request");
		String code = request.getParameter("code");
		String state = request.getParameter("state");
		String env = request.getParameter("env");
		String platform = request.getParameter("platform");
		log.info("wechat授权跳转参数,env:"+env+",requestUrl:"+requestUrl+",code:"+code+",state:"+state);
		String redirectUrl = oauthWechatConfiguration.getRedirectProdUrl();
		if("dev".equals(env)){
			redirectUrl = oauthWechatConfiguration.getRedirectDevUrl();
		}else if("test".equals(env)){
			redirectUrl = oauthWechatConfiguration.getRedirectTestUrl();
		}else if("pre-prod".equals(env)){
			redirectUrl = oauthWechatConfiguration.getRedirectPreProdUrl();
		}
		String url = redirectUrl+requestUrl+"?platform="+platform+"&code="+code+"&state="+state;
		log.info("wechat授权跳转地址为:"+ url);
		response.sendRedirect(url);
	}
@Configuration
@ConfigurationProperties(prefix = "oauth.wechat")
public class OauthWechatConfiguration {
	private String redirectDevUrl;
	private String redirectTestUrl;
	private String redirectPreProdUrl;
	private String redirectProdUrl;
	private String appId;
	private String appSecret;
	private String env;
	
	//setter and getter...
}

application.yml

oauth:
    wechat:
      redirectDevUrl: http://localhost:4201
      redirectTestUrl: http://192.168.1.10:30080
      redirectPreProdUrl: http://192.168.1.20:30080
      redirectProdUrl: https://admin.loooswc.cn
      appId: xxxxxxxxxx
      appSecret: xxxxxxxxxx
      env: dev # dev研发 test测试 pre-prod准生产 prod生产

微信授权回调域填写admin.loooswc.cn
微信扫码登录只能填一个授权回调域问题_第2张图片
调用请求时redirect_url填写https://admin.loooswc.cn/oauth/wechat/redirect.do?env=dev&request=/oauth/wechat/login.do,当然是通过urlEncode处理过的。

这样就可以实现一个授权回调域对多个域名有效的效果了

你可能感兴趣的:(java)