URL 参数与 ADAL.js 和 UI-Router 的重定向问题
Redirection issue with URL parameter with ADAL.js and UI-Router
我使用 url 参数配置了包含 url 的状态,如下所示:url:route/:id1/:id2:id3
使用 ADAL js。当我用 route/1/2/3
命中 url 时,登录后,我被重定向到 route/:id1/:id2/:id3?id1=1&id2=2&id3=3
而不是 route/1/2/3
。
我进一步调查,在 adal-angular.js 文件中,我们将浏览器 url 设置为 $location.url().search(jsonParameters)
,其中 jsonParameters
是具有值 json 的对象=21=] 导致 url 畸形。
你们能否为我指明正确的方向,以解决这个问题并重定向到正确的 url?
编辑:添加代码示例
我已经按照下面的说明配置了 AAD 路由:
$stateProvider
.state('State1', {
templateUrl: getViewUrl('viewUrl'),
controller: 'homeController',
controllerAs: 'home',
url: '/route/:id1/:id2/:id3',
requireADLogin: true
})
我正在按以下方式初始化 adal 服务提供者:
$locationProvider.html5Mode(false);
var endpoints = {}
endpoints[EnvironmentConfig.url1] = EnvironmentConfig.url1;
endpoints[EnvironmentConfig.url2] = EnvironmentConfig.url2;
adalAuthenticationServiceProvider.init(
{
instance: EnvironmentConfig.aadUrl, // 'https://login.microsoftonline.com/',
tenant: EnvironmentConfig.tenant, // 'microsoft.onmicrosoft.com',
clientId: EnvironmentConfig.clientId,
endpoints: endpoints,
loginResource: EnvironmentConfig.breServiceADUrl
//cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
}, $httpProvider);
谢谢。
我测试的代码和你的好像没什么区别,我post代码供你参考。希望对您有所帮助:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal-angular.min.js"></script>
<script src="//unpkg.com/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="homeCtrl">
<ul class="nav navbar-nav navbar-right">
<li><a ui-sref="hello({id1:1,id2:2,id3:1})" ui-sref-active="active">Hello</a></li>
<li><a href="#hello/1/2/3" ui-sref-active="active">Hello2</a></li>
<li><a ui-sref="about" ui-sref-active="active">About</a></li>
<li ng-show="userInfo.isAuthenticated"><a href="" ng-click="logout()">Logout</a></li>
<li><a href="" ng-hide="userInfo.isAuthenticated" ng-click="login()">Login</a></li>
</ul>
<ui-view></ui-view>
</div>
</div>
<script>
var myApp = angular.module('myApp', ['AdalAngular', 'ui.router', 'ngRoute'])
.config(['$httpProvider', 'adalAuthenticationServiceProvider', '$stateProvider', '$routeProvider', function ($httpProvider, adalProvider, $stateProvider, $routeProvider) {
var endpoints = {
"https://localhost:44327/": "https://adfei.onmicrosoft.com/ToGoAPI",
};
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'xxx.onmicrosoft.com',
clientId: '{clientId}',
extraQueryParameter: 'nux=1',
endpoints: endpoints,
},
$httpProvider
);
var helloState = {
name: 'hello',
url: '/hello/:id1/:id2/:id3',
template: '<h3>hello world!</h3>',
controller: function ($stateParams) {
},
requireADLogin: true
}
var aboutState = {
name: 'about',
url: '/about',
template: '<h3>Its the UI-Router hello world app!</h3>'
}
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
$routeProvider.
when("/hello/:id1/:id2/:id3", {
controller: "homeCtrl",
templateUrl: '<h3>hello world!-ngRoute</h3>',
requireADLogin: true
});
}])
myApp.controller('homeCtrl', ['$scope', '$http', 'adalAuthenticationService', '$location', function ($scope, $http, adalService, $location, $stateParams) {
$scope.double = function (value) { return value * 2; };
$scope.login = function () {
adalService.login();
};
$scope.logout = function () {
adalService.logOut();
};
}]);
</script>
</body>
</html>
要测试代码,首先单击登录,然后您可以通过单击 Hello 和 About 超链接切换视图。
更新
#345 的 ADAL 版本 1.0.12
似乎解决了这个问题。建议您将ADAL升级到最新的1.0.13版本来解决这个问题。
我阅读了 adal-angular.js 的源代码,发现使用 url 参数重定向到 link 时存在问题。我修改了@Fei Xue 的代码以重现该场景。
<!-- inject:css -->
<!-- endinject -->
<!-- bower:js -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal-angular.min.js"></script>
<script src="//unpkg.com/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<!-- endinject -->
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<base href="/">
</head>
<body>
<div >
<div ng-controller="homeCtrl">
<ul class="nav navbar-nav navbar-right">
<li><a ui-sref="hello({id1:1,id2:2,id3:1})" ui-sref-active="active">Hello</a></li>
<li><a href="#hello/1/2/3" ui-sref-active="active">Hello2</a></li>
<li><a ui-sref="about" ui-sref-active="active">About</a></li>
<li ng-show="userInfo.isAuthenticated"><a href="" ng-click="logout()">Logout</a></li>
<li><a href="" ng-hide="userInfo.isAuthenticated" ng-click="login()">Login</a></li>
</ul>
<ui-view></ui-view>
</div>
</div>
</body>
</html>
<script>
var myApp = angular.module('myApp', ['AdalAngular', 'ui.router'])
.config(['$httpProvider', 'adalAuthenticationServiceProvider', '$stateProvider','$locationProvider','$urlRouterProvider', function ($httpProvider, adalProvider, $stateProvider,$locationProvider,$urlRouterProvider) {
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix('');
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'xxx.onmicrosoft.com',
clientId: '<clientId>',
},
$httpProvider
);
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded; charset=utf-8";
var helloState = {
name: 'hello',
url: '/hello/:id1/:id2/:id3',
template: '<h3>hello world!</h3>',
controller: function ($stateParams) {
// alert('kiran');
},
requireADLogin: true
}
var aboutState = {
name: 'about',
url: '/about',
template: '<h3>Its the UI-Router hello world app!</h3>'
}
var homeState={
name:'home',
url:'/',
controller:function(){
},
requireADLogin:true
}
$stateProvider.state(homeState);
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
$urlRouterProvider.otherwise('/');
}])
myApp.controller('homeCtrl', ['$scope', '$http', 'adalAuthenticationService', '$location','$stateParams','$rootScope','$timeout', function ($scope, $http, adalService, $location, $stateParams,$rootScope,$timeout) {
$scope.double = function (value) { return value * 2; };
$scope.login = function () {
adalService.login();
};
$scope.logout = function () {
adalService.logOut();
};
/*Fix for adal issue*/
// $rootScope.$on("adal:loginSuccess", function (e) {
// console.log('loginSuccess');
//
// $timeout(function () {
// var startPageURL = sessionStorage['adal.start.page'];
// var stateParamsString = sessionStorage['adal.start.page.params'];
//
// var stateParamsJson = stateParamsString ? JSON.parse(stateParamsString) : {};
//
//var matchedState = _.find($state.get(),
// function (state) {
// return state.url == startPageURL;
/// });
// if (matchedState) {
// $state.go(matchedState.name, stateParamsJson, { reload: true });
// }
// }, 2);
// });
}]);
</script>
我也添加了修复程序。 Adal-angular使用location.search方法替换登录成功后重定向的url。但是搜索方法将存储的 json 对象转换为导致问题的查询参数。
您可以 运行 下面的代码按原样重现问题。在隐身浏览器中,如果我们尝试转到 http://localhost:8080/hello/1/2/3
,它会将我们重定向到 http://localhost:8080/#/hello/:id1/:id2/:id3?id1=1&id2=2&id3=1
,这是错误的。
我已经评论了这个问题的修复。取消注释代码后,它将按预期工作,并将我们正确重定向到 http://localhost:8080/hello/1/2/3
我使用 url 参数配置了包含 url 的状态,如下所示:url:route/:id1/:id2:id3
使用 ADAL js。当我用 route/1/2/3
命中 url 时,登录后,我被重定向到 route/:id1/:id2/:id3?id1=1&id2=2&id3=3
而不是 route/1/2/3
。
我进一步调查,在 adal-angular.js 文件中,我们将浏览器 url 设置为 $location.url().search(jsonParameters)
,其中 jsonParameters
是具有值 json 的对象=21=] 导致 url 畸形。
你们能否为我指明正确的方向,以解决这个问题并重定向到正确的 url?
编辑:添加代码示例
我已经按照下面的说明配置了 AAD 路由:
$stateProvider
.state('State1', {
templateUrl: getViewUrl('viewUrl'),
controller: 'homeController',
controllerAs: 'home',
url: '/route/:id1/:id2/:id3',
requireADLogin: true
})
我正在按以下方式初始化 adal 服务提供者:
$locationProvider.html5Mode(false);
var endpoints = {}
endpoints[EnvironmentConfig.url1] = EnvironmentConfig.url1;
endpoints[EnvironmentConfig.url2] = EnvironmentConfig.url2;
adalAuthenticationServiceProvider.init(
{
instance: EnvironmentConfig.aadUrl, // 'https://login.microsoftonline.com/',
tenant: EnvironmentConfig.tenant, // 'microsoft.onmicrosoft.com',
clientId: EnvironmentConfig.clientId,
endpoints: endpoints,
loginResource: EnvironmentConfig.breServiceADUrl
//cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
}, $httpProvider);
谢谢。
我测试的代码和你的好像没什么区别,我post代码供你参考。希望对您有所帮助:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal-angular.min.js"></script>
<script src="//unpkg.com/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="homeCtrl">
<ul class="nav navbar-nav navbar-right">
<li><a ui-sref="hello({id1:1,id2:2,id3:1})" ui-sref-active="active">Hello</a></li>
<li><a href="#hello/1/2/3" ui-sref-active="active">Hello2</a></li>
<li><a ui-sref="about" ui-sref-active="active">About</a></li>
<li ng-show="userInfo.isAuthenticated"><a href="" ng-click="logout()">Logout</a></li>
<li><a href="" ng-hide="userInfo.isAuthenticated" ng-click="login()">Login</a></li>
</ul>
<ui-view></ui-view>
</div>
</div>
<script>
var myApp = angular.module('myApp', ['AdalAngular', 'ui.router', 'ngRoute'])
.config(['$httpProvider', 'adalAuthenticationServiceProvider', '$stateProvider', '$routeProvider', function ($httpProvider, adalProvider, $stateProvider, $routeProvider) {
var endpoints = {
"https://localhost:44327/": "https://adfei.onmicrosoft.com/ToGoAPI",
};
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'xxx.onmicrosoft.com',
clientId: '{clientId}',
extraQueryParameter: 'nux=1',
endpoints: endpoints,
},
$httpProvider
);
var helloState = {
name: 'hello',
url: '/hello/:id1/:id2/:id3',
template: '<h3>hello world!</h3>',
controller: function ($stateParams) {
},
requireADLogin: true
}
var aboutState = {
name: 'about',
url: '/about',
template: '<h3>Its the UI-Router hello world app!</h3>'
}
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
$routeProvider.
when("/hello/:id1/:id2/:id3", {
controller: "homeCtrl",
templateUrl: '<h3>hello world!-ngRoute</h3>',
requireADLogin: true
});
}])
myApp.controller('homeCtrl', ['$scope', '$http', 'adalAuthenticationService', '$location', function ($scope, $http, adalService, $location, $stateParams) {
$scope.double = function (value) { return value * 2; };
$scope.login = function () {
adalService.login();
};
$scope.logout = function () {
adalService.logOut();
};
}]);
</script>
</body>
</html>
要测试代码,首先单击登录,然后您可以通过单击 Hello 和 About 超链接切换视图。
更新
#345 的 ADAL 版本 1.0.12
似乎解决了这个问题。建议您将ADAL升级到最新的1.0.13版本来解决这个问题。
我阅读了 adal-angular.js 的源代码,发现使用 url 参数重定向到 link 时存在问题。我修改了@Fei Xue 的代码以重现该场景。
<!-- inject:css -->
<!-- endinject -->
<!-- bower:js -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal.min.js"></script>
<script src="https://secure.aadcdn.microsoftonline-p.com/lib/1.0.10/js/adal-angular.min.js"></script>
<script src="//unpkg.com/angular-ui-router/release/angular-ui-router.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<!-- endinject -->
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<base href="/">
</head>
<body>
<div >
<div ng-controller="homeCtrl">
<ul class="nav navbar-nav navbar-right">
<li><a ui-sref="hello({id1:1,id2:2,id3:1})" ui-sref-active="active">Hello</a></li>
<li><a href="#hello/1/2/3" ui-sref-active="active">Hello2</a></li>
<li><a ui-sref="about" ui-sref-active="active">About</a></li>
<li ng-show="userInfo.isAuthenticated"><a href="" ng-click="logout()">Logout</a></li>
<li><a href="" ng-hide="userInfo.isAuthenticated" ng-click="login()">Login</a></li>
</ul>
<ui-view></ui-view>
</div>
</div>
</body>
</html>
<script>
var myApp = angular.module('myApp', ['AdalAngular', 'ui.router'])
.config(['$httpProvider', 'adalAuthenticationServiceProvider', '$stateProvider','$locationProvider','$urlRouterProvider', function ($httpProvider, adalProvider, $stateProvider,$locationProvider,$urlRouterProvider) {
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix('');
adalProvider.init(
{
instance: 'https://login.microsoftonline.com/',
tenant: 'xxx.onmicrosoft.com',
clientId: '<clientId>',
},
$httpProvider
);
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded; charset=utf-8";
var helloState = {
name: 'hello',
url: '/hello/:id1/:id2/:id3',
template: '<h3>hello world!</h3>',
controller: function ($stateParams) {
// alert('kiran');
},
requireADLogin: true
}
var aboutState = {
name: 'about',
url: '/about',
template: '<h3>Its the UI-Router hello world app!</h3>'
}
var homeState={
name:'home',
url:'/',
controller:function(){
},
requireADLogin:true
}
$stateProvider.state(homeState);
$stateProvider.state(helloState);
$stateProvider.state(aboutState);
$urlRouterProvider.otherwise('/');
}])
myApp.controller('homeCtrl', ['$scope', '$http', 'adalAuthenticationService', '$location','$stateParams','$rootScope','$timeout', function ($scope, $http, adalService, $location, $stateParams,$rootScope,$timeout) {
$scope.double = function (value) { return value * 2; };
$scope.login = function () {
adalService.login();
};
$scope.logout = function () {
adalService.logOut();
};
/*Fix for adal issue*/
// $rootScope.$on("adal:loginSuccess", function (e) {
// console.log('loginSuccess');
//
// $timeout(function () {
// var startPageURL = sessionStorage['adal.start.page'];
// var stateParamsString = sessionStorage['adal.start.page.params'];
//
// var stateParamsJson = stateParamsString ? JSON.parse(stateParamsString) : {};
//
//var matchedState = _.find($state.get(),
// function (state) {
// return state.url == startPageURL;
/// });
// if (matchedState) {
// $state.go(matchedState.name, stateParamsJson, { reload: true });
// }
// }, 2);
// });
}]);
</script>
我也添加了修复程序。 Adal-angular使用location.search方法替换登录成功后重定向的url。但是搜索方法将存储的 json 对象转换为导致问题的查询参数。
您可以 运行 下面的代码按原样重现问题。在隐身浏览器中,如果我们尝试转到 http://localhost:8080/hello/1/2/3
,它会将我们重定向到 http://localhost:8080/#/hello/:id1/:id2/:id3?id1=1&id2=2&id3=1
,这是错误的。
我已经评论了这个问题的修复。取消注释代码后,它将按预期工作,并将我们正确重定向到 http://localhost:8080/hello/1/2/3