1、问题背景描述:
我有一个困扰了很久项目需求,前台门户用的MVC,前台登录之后需要能点击某个按钮就能进入后台vue开发的前端项目,不需要重新登录。这个需求中mvc项目相对于vue项目来说是外部链接,他要跳转到vue项目,并传递登录的用户信息给vue项目,才能让vue项目免除登录。
首先前台门户的mvc项目跟后台vue项目他们是不同的站点,mvc项目端口是9995,vue项目的端口是9995。 那这样肯定是跨域了的,所以前台登录后存储的cookie也好,localStorage也好,后台vue项目肯定都是访问不到的。那这个时候跳转链接唯一能传递参数的办法就是url地址里面传递。
2、前台mvc项目实现
我使用了一个mvc的action控制器来在后端取得cookie中的用户信息,组成url,实现跳转。
其实也可以在前端用jequry来实现,不过记得一点,如果你的参数值里有中文,要做url的编码HttpUtility.UrlEncode(userName) ,_adminUrl变量的值是目标站点根地址,是我在配置文件中配置的,要自己在控制器构造函数中提前取出。
经过测试实践:后端控制器代码实现跳转的方式,在windows里面调试运行时没问题,但是发布到linux里面运行,Response.Redirect(_adminUrl); 这个跳转会产生500错误。我的.netcore项目还是配置过跨域的,哪怕是把服务器发布后的域名地址都配置允许跨域,都没用。所以我又用前端js方式实现了一次跳转,避开linux中运行时跨域跳转不了的坑。
前端实现都是些很基础的代码,详见(2)前端jquery实现跳转代码
(1)控制器实现代码:
[HttpPost, HttpGet, Route("toAdmin")]public IActionResult toAdmin(){ var mytoken = HttpContext.Request.Cookies.TryGetValue("portalusertoken", out string myuser);//读取HttpContext.Request.Cookies.TryGetValue("portaluserid", out string user_Id);//读取HttpContext.Request.Cookies.TryGetValue("portalusername", out string userName);//读取HttpContext.Request.Cookies.TryGetValue("portalimg", out string img);//读取//_adminUrlif (mytoken && !string.IsNullOrEmpty(myuser)){ var urlparam="?userName="+ HttpUtility.UrlEncode(userName) + "&user_Id="+ user_Id + "&img="+ img + "&token=" + myuser; // +"&token=" + myuser _adminUrl = _adminUrl + urlparam;Response.Redirect(_adminUrl);}//下面这段代码其实只是预防,为了避免取不到token,上面跳转失败,可能就只是简单的返回一个下面的登录成功结果,意义不大。if (mytoken && !string.IsNullOrEmpty(myuser)){webResponse.Status = true;webResponse.Data = myuser;webResponse.OK(ResponseType.LoginSuccess);}else{webResponse.Status = false;}return Json(webResponse);}
(2)前端jquery实现跳转代码:
var cookietokenvalue = $.cookie('portalusertoken');var cookieusername = $.cookie('portalusername');var portaluserid = $.cookie('portaluserid');var portalimg = $.cookie('portalimg');var adminUrl = $.cookie('_adminUrl');
var myurlhouzhui= "?userName=" + encodeURI(cookieusername) + "&user_Id=" + portaluserid + "&img=" + portalimg + "&token=" + cookietokenvalue;
var myhostname = location.hostname;
var houtaiurl = "http://" + myhostname + ":" + adminUrl + myurlhouzhui;
$("#a_toadmin").click(function () {location.href = houtaiurl; //跳转
});
3、后台vue项目接收解析url中的用户信息
这一步其实vue比较熟悉的朋友很容易就想到了,用router.beforeEach 钩子函数来拦截路由,然后解析url中的参数,一般情况下vue项目内部路由之间是不可能去通过url来传递参数的,所以这个地方其实加了拦截规则也只会对外部跳转url的参数有用。有点项目可能不一定写了router.beforeEach拦截,如果没有就自己加router.beforeEach函数实现。我的项目是第三方开源项目,他的router.beforeEach是写在了index.js文件中。
//获取URL中参数的值,中文解码
function getQueryVariable(url,variable,num)
{var query =url.substring(num);var vars = query.split("&");for (var i=0;i<vars.length;i++) {var pair = vars[i].split("=");if(pair[0] == variable){return decodeURI(pair[1]);}}return(null);
}
router.beforeEach((to, from, next) => {debugger;//路由拦截解析外部跳转过来的url参数--开始// let myurluncode = decodeURIComponent(to.path);// to.path = myurluncode;// to.fullPath = myurluncode;// to.href = myurluncode; let userName = getQueryVariable(to.fullPath, "userName",6);let user_Id = getQueryVariable(to.fullPath, "user_Id",6);let img = getQueryVariable(to.fullPath, "img",6);let token = getQueryVariable(to.fullPath, "token",6);if (user_Id != null) {localStorage.setItem("user", JSON.stringify({"user_Id":user_Id,"img":img,"userName":userName,"token":token})); next({ path: '/', query: { redirect: Math.random() } }); //跳转到根目录}//路由拦截解析外部跳转过来的url参数---结束if (to.matched.length == 0) return next({ path: '/404' });//2020.06.03增加路由切换时加载提示store.dispatch("onLoading", true);if ((to.hasOwnProperty('meta') && to.meta.anonymous) || store.getters.isLogin() || to.path == '/login') {return next();}next({ path: '/login', query: { redirect: Math.random() } });
})
4、跳转前后界面效果展示