• angularjs+webapi2 跨域Basic 认证授权(二)


    在上一篇中大概演示了 整个认证授权的过程。今天在这篇博客中将结合上一篇的例子继续在跨域的情况

    我们用ionic 写一个简单的页面

    值得注意的是 在ionic.bundle.js 里面集成了angularjs 所以不用额外去引用angularjs 文件

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
          <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title></title>
        <link href="ionic-v1.3.0/css/ionic.min.css" rel="stylesheet" />
             <script src="ionic-v1.3.0/js/ionic.bundle.min.js"></script>
       
    </head>
    <body ng-app="basicApp" ng-controller="app.login as vm">
        <ion-content>
                 <ion-list ng-repeat="data in vm.datas">
                <ion-item>
                    {{data}}
                </ion-item>
            </ion-list>
        </ion-content>
    </body>
    </html>

    相关的js文件

    <script type="text/javascript">
            (function () {
                var app=angular.module('basicApp', ['ionic']);
        
               
           app .controller('app.login', ['$http',function ($http) {
                var vm = this;
                vm.datas = [];
          
                vm.getValue = function () {
                    $http({
                        url: "http://localhost:1894/api/basic/get",
                        method: 'GET'
                           }).success(function (datas) {
                        vm.datas = datas;
                    }).error(function (data,status) {
                        if (status == '401') {
                          
                        }
                    });
                }
              
                vm.getValue();
            }]);
            })();
           </script>

    运行看一下效果,不出意外的话

    image

    在web.config 里面添加如下配置

    <system.webServer>    
    <httpProtocol>
          <customHeaders>
            <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept, authorization" />
            <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE,OPTIONS" />
            <add name="Access-Control-Allow-Origin" value="*"/>
          </customHeaders>
        </httpProtocol>
      </system.webServer>

    这里的配置有些地方是后面需要用到的,为了减少篇幅,这里一并贴出来了。

    配置完成之后 刷新页面,不出意外的话

    image

    因为在我们这个跨域请求header 里面 并没有Authorization 相关信息,在上一篇浏览器登录之后的信息里面可以看到

    $http({
                        url: "http://localhost:1894/api/basic/get",
                        method: 'GET',
                        headers:{'Authorization':'Basic dHp5OjEyMw=='}
                      
                    }).success(function (datas) {
                        vm.datas = datas;
                    }).error(function (data,status) {
                        if (status == '401') {
                            //局部处理的方式
                            //document.getElementById('logindiv').style.display = "block";
                        }
                    });

    在代码中加入红色部分   'Basic dHp5OjEyMw==' (为了理解这个过程这里是用的之前浏览器生成的那个header 里面的authorization信息)

    然后再看看效果

    image

    然后需要注意的是

    image

    这里有一个options 请求:这是在跨域的情况下浏览器会发送一个试探请求(具体的百度一下)

    所以我们在webapi 的get   action 上面要加上 HttpOptions (这里跟之前说的webconfig配置也有关系)

    不然的话在进行options请求的时候会返回405错误,导致整个请求没法进行

    [HttpBasicAuthorize]
        public class BasicController : ApiController
        {
             [HttpOptions]
             [HttpGet]
            public IEnumerable<string> Get() {
                return new string[] { "tzy","123"};
            }
    }

    好了,到这里呢 这个ajax 跨域请求的过程也模拟完成。不过很明显还差了些东西,我们接下来就通过自己的登陆界面和方式来替换刚才给定的header 里面的 authorization 参数:

    1,建一个登陆页面(为了好理解,还是在刚才那个页面上吧)

    <ion-content>
            <div class="list"  id="logindiv" style="display:none">
                <label class="item item-input">
                    <input type="text" placeholder="用户名" ng-model="vm.user.name" />
                </label>
                <label class="item item-input">
                    <input type="text" placeholder="密码" ng-model="vm.user.password" />
                </label>
    
                <label>
                    <button class="button button-block button-balanced" ng-click="vm.loginSubmit(vm.user)">
                        <i class="ion ion-android-add"></i>&nbsp;登录
                    </button>
                </label>
            </div>
            <ion-list ng-repeat="data in vm.datas">
                <ion-item>
                    {{data}}
                </ion-item>
            </ion-list>
        </ion-content>

    在之前的代码中插入了 一个 id=logindiv 的内容 默认是隐藏的

    然后实现我们的login api

            [AllowAnonymous]
            [HttpOptions]
            [HttpPost]
            public LoginResult Login(UserDto user)
            {
                if (user != null)
                {
                    if (user.Name.Equals("tzy") && user.Password.Equals("123"))
                    {
                        // return new HttpResponseMessage(
                        string s = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(String.Format("{0}:{1}", user.Name, user.Password)));
                        return new LoginResult() { Success = true, Token = s };
                    }
                }
                return new LoginResult() { Success = false, Token = null };
            }

    这里贴一下 UserDto 和 LoginResult类

    public class LoginResult {
            public bool Success { get; set; }
            public string Token { get; set; }
        }
        public class UserDto {
            public string Name { get; set; }
            public string Password { get; set; }
        }

    [AllowAnonymous]  就是允许未验证访问

     string s = Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(String.Format("{0}:{1}", user.Name, user.Password)));   这句代码就体现了基础认证加密实现 ,这也就是为什么说basic认证是不安全的,但这不是今天要讨论的问题,我们重在理解这个过程 ,至于加密方式 在过程的基础上都可以加强。

    然后再实现一下 客户端ajax 请求登录的代码

     

    vm.loginSubmit = function (user) {
                    console.log(user);
                    $http({
                        url: "http://localhost:1894/api/basic/login",
                        method:'POST',
                        data: user
    
    
                    }).success(function (result) {
                        if (result.Success) {
                           // localStorage.token = result.Token;
                            localStorage.setItem('token', result.Token);
                            console.log(localStorage.getItem('token'));
                            vm.getValue();
                            document.getElementById('logindiv').style.display = "none";
                        }
                    });
                }

    我们用 localStorage 把收到的 token 存储起来

    然后把之前的 getValue 更改一下

    vm.getValue = function () {
                    $http({
                        url: "http://localhost:1894/api/basic/get",
                        method: 'GET',
                        headers: { 'Authorization': 'Basic ' + localStorage.getItem('token') }
                      
                    }).success(function (datas) {
                        vm.datas = datas;
                    }).error(function (data,status) {
                        if (status == '401') {
                            //如果认证没有通过  则显示登陆界面
                            document.getElementById('logindiv').style.display = "block";
                        }
                    });
                }

    改动有2点:1 headers  authorization 的值  从localStorage中取

                    2.在每次请求 如果401 认证失败  就显示登录界面

    然后让我们看一下效果吧:

    testdemo

    这个gif 能很清楚的看到这个过程 -》在第一次请求getValue 的时候 报了一个401 错误然后登陆之后拿到token信息(其实就是认证信息),然后再次请求成功。

       后续可能会利用angularjs 的拦截器机制  统一拦截处理 httpstatus 问题。

  • 相关阅读:
    spring-mvc-继续学习
    springMVC学习
    spring-jdbc及事务
    Spring-MVC配置思路
    spring入门-注解的使用
    spring入门
    Spring MVC——数据校验(分组校验)
    Spring MVC——数据校验(数据回显)
    Spring MVC——数据检验步骤
    Spring MVC——参数装填方式
  • 原文地址:https://www.cnblogs.com/bninp/p/5512057.html
Copyright © 2020-2023  润新知