angular-ui replace'?' with '#' on

2019-04-19 08:14发布

问题:

I'm implementing facebook ouath login in angularjs without SDK.

Everything works as expected except one thing.

When user click on login button, which redirects to facebook login page, after successfull login, facebook fires redirect_uri URL, and user is again in the app.

Problem is, that ui-router (probably) replaces '?' with '#' in path, so

http://localhost/fbauth?access_token=xxx&code=yyy
becomes
http://localhost/fbauth#access_token=xxx&code=yyy

Because of that, i cannot use $stateParams to get object with query params.

Suprisingly, when I manually enter in browser or click link to http://localhost/fbauth?access_token=xxx&code=yyy
everything works properly, and ui-router does not replace '?' with '#'.

I guess, that it's related to redirection scenario itself.

Can someone point me what I do wrong, or how to change ui-router behaviour in this case?

This is the state, that handles fb redirect:

.state('fbauth', {
  url: '/fbauth?access_token&code&expires_in',
  templateUrl: 'static/public/public.html',
  controller: 'publicCtrl'
});

PS ui-router is set to work in html5 mode with $locationProvider.html5Mode(true);

回答1:

You can add this resolve function to your state, which will replace a hash url with the query string url:

resolve: {
    'urlFix': ['$location', function($location){
        $location.url($location.url().replace("#","?"));
     }]
}
  • So a url of /fbauth#access_token=123456&code=abcde&expires_in=99999999 would be redirected automatically
  • Becoming /fbauth?access_token=123456&code=abcde&expires_in=99999999
  • $stateParams would be populated correctly.
  • The value would be {access_token: "123456", code: "abcde", expires_in: "99999999"}
  • $location.url() doesn't update if the location matches already, so the state won't redirect when there is no # present.

Full example code:

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js"></script>
    <meta charset="utf-8">
    <title>FBAUTH</title>
</head>
<body ng-app="app">
    <base href="/">
    <div ui-view></div>
    <script>
        angular.module('app', ['ui.router'])
            .controller('publicCtrl', ['$scope','$stateParams', function($scope, $stateParams) {
                // $stateParams should be correctly set (even for hash route)
                console.log($stateParams);
            }])
            .config(['$locationProvider','$stateProvider', function($locationProvider, $stateProvider){
                $stateProvider
                    .state("fbauth",
                    {
                        url: '/fbauth?access_token&code&expires_in',
                        templateUrl: 'fbauth.html',
                        controller: 'publicCtrl',
                        resolve: {
                            'urlFix': ['$location', function($location){
                                $location.url($location.url().replace("#","?"));
                            }]
                        }
                    });

                $locationProvider.html5Mode(true);
            }]);
    </script>
</body>
</html>


回答2:

I would not prefer passing query parameters(using ? mark) in client side routing. Instead you can use route/state params as follows:

http://localhost/#/fbauth/access_token/:access_token/code/:code

and you can access these values using $stateParams. e.g. ($stateParams.access_token)