• Orchard Core 增加了一个API模块,要怎么调用


    如下,我在Orchard Core框架中添加了一个API的模块,并且定义了对应的权限才可以调用,那么我们现在考虑的就是要怎么去调用它。

    首先,我们用Fiddler查看下我们正常的登录的http报文,直接在浏览器输入路径例如: http://192.168.0.225:8082/admin ,会直接跳转到登录页,路径是:http://192.168.0.225:8082/Login?ReturnUrl=%2Fadmin

    admin被添加到一个ReturnUrl的参数后面,输入账号密码然后回车登录到后台。这样一个登录操作就完成了,我们再看看Fiddler的报文:

    在login的时候发送了一个__RequestVerificationToken参数,并且在返回的时候set了一个cookie,这个cookie包含了这个登录用户的身份信息等等,

    所以当我们关闭浏览器但没有logout退出,再次进入admin后台时,不需要再次登录操作,就是因为在这个时候记录了cookie。

    那么__RequestVerificationToken参数又是怎么来的呢?我们知道这整个过程,每一个http报文都是紧接着上一条报文的结果,

    我们看看上一个报文,它返回了一个Document,我们在这个Document找到了这个元素 name="__RequestVerificationToken" 

    这个元素的value就是__RequestVerificationToken参数的值。

    再看看这个Document,里面有一个Form,意思就是Form里的内容会submit到Form对应的action中。

    我一开始以为,了解了这个过程,我们就可以用ajax模拟登录得到cookie了,但是用如下代码,返回的总是400错误,浏览器拒绝了请求。

    $.ajax({
                    url: 'http://192.168.0.225:8082/admin',
                    type: 'get',
                    cache: false,
                    success: function (data) {
                        var objval = $(data).find("[name='__RequestVerificationToken']").val();
                        var url = $(data).find(".form-horizontal").attr("action");
                        $.ajax({
                            url: "http://192.168.0.225:8082" +url,
                            type: 'post',
                            cache: false,
                            async: false,
                            data: {
                                'UserName': 'admin',
                                'Password': 'XXXXXXXXX',
                                '__RequestVerificationToken': objval,
                                'RememberMe': false
                            },
                            success: function (data, status, xhr) {
                                alert("ok");
                                console.log(xhr.getAllResponseHeaders());
                            }
                        });
                    }
                });
    

    这里猜测,估计是因为浏览器的安全机制,拦截了我的ajax

    那么我就换C#模拟http请求,可以得到我要的API返回的结果,代码如下:

    //发送请求
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://192.168.0.225:8082");
                    try
                    {
                        //在没有登录之前,不管写什么路径,都会跳到login页面,而所写的路径会自动添加到returnurl这个参数后
                        //登录之后就会跳转到这个页面
                        //这一步是为了拿到__RequestVerificationToken
                        var cliPost = client.GetAsync("/warehouseapi/admin/index");
                        cliPost.Wait();
                        var result = cliPost.Result;
                        string resultContent = result.Content.ReadAsStringAsync().Result;
                        //返回了一个Document对象,用NSoup解析,NSoup可以用像jQuery那样的选择器选择元素
                        var htmlDoc = NSoup.NSoupClient.Parse(resultContent);
                        var __RequestVerificationToken = htmlDoc.Select("[name=__RequestVerificationToken]").Val();
                        var actionPath = htmlDoc.Select(".form-horizontal").Attr("action");
                        //准备Post的参数
                        var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("UserName", "admin"),
                                                                    new KeyValuePair<string, string>("Password", "ZXXXXXXXX@"),
                                                                    new KeyValuePair<string, string>("RememberMe", "false"),
                                                                    new KeyValuePair<string, string>("__RequestVerificationToken", __RequestVerificationToken),
    
                            });
                        try
                        {
                            //发送请求
                            //登录
                            var cliPost1 = client.PostAsync(actionPath, content);
                            cliPost1.Wait();
                            var result1 = cliPost1.Result;
                            string resultContent1 = result.Content.ReadAsStringAsync().Result;
    
                            //向API发送请求
                            var cliGet = client.GetAsync("/warehouseapi/admin/index");
                            cliGet.Wait();
                            var resultGet = cliGet.Result;
                            string resultContent2 = resultGet.Content.ReadAsStringAsync().Result;
                            Console.WriteLine(DateTime.Now + "======" + resultContent2);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                Console.Read();
    

      

     补充:上面是get请求方式,如果是post请求的时候,由于框架有ValidateAntiForgeryToken这个的验证,所以每次请求都要带上一个__RequestVerificationToken参数。

    ValidateAntiForgeryToken的用途是防止CSRF(跨网站请求伪造),这个具体的可以百度了解。

    总之每次post请求一个api路径都要带上__RequestVerificationToken参数,而__RequestVerificationToken参数是基于上一次请求返回的html页面中[name="__RequestVerificationToken"]的hidden标签的值,这个值每次是不一样的。

    post请求的示例如下:

    //发送请求
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://192.168.0.225:8082");
                    try
                    {
                        //在没有登录之前,不管写什么路径,都会跳到login页面,而所写的路径会自动添加到returnurl这个参数后
                        //登录之后就会跳转到这个页面
                        //这一步是为了拿到__RequestVerificationToken
                        var cliPost = client.GetAsync("/Login?ReturnUrl=%2Fadmin");
                        cliPost.Wait();
                        var result = cliPost.Result;
                        string resultContent = result.Content.ReadAsStringAsync().Result;
                        //返回了一个Document对象,用NSoup解析,NSoup可以用像jQuery那样的选择器选择元素
                        var htmlDoc = NSoup.NSoupClient.Parse(resultContent);
                        var __RequestVerificationToken = htmlDoc.Select("[name=__RequestVerificationToken]").Val();
                        var actionPath = htmlDoc.Select(".form-horizontal").Attr("action");
                        //准备Post的参数 用户名、密码错误会跳回登录页
                        var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("UserName", "wXXXXXi"),
                                                                    new KeyValuePair<string, string>("Password", "XXXXXXXX21"),
                                                                    new KeyValuePair<string, string>("RememberMe", "false"),
                                                                    new KeyValuePair<string, string>("__RequestVerificationToken", __RequestVerificationToken),
                        });
                        try
                        {
                            //发送请求
                            //登录
                            var cliPost1 = client.PostAsync(actionPath, content);
                            cliPost1.Wait();
                            var result1 = cliPost1.Result;
                            string resultContent1 = result1.Content.ReadAsStringAsync().Result;
    
                            //返回了一个Document对象,用NSoup解析,NSoup可以用像jQuery那样的选择器选择元素
                            var htmlDoc1 = NSoup.NSoupClient.Parse(resultContent1);
                            var __RequestVerificationToken1 = htmlDoc1.Select("[name=__RequestVerificationToken]").Val();
                            var actionPath1 = htmlDoc1.Select(".form-horizontal").Attr("action");
    
                            //var cliGet = client.GetAsync("/warehouseapi/admin/index");
                            //cliGet.Wait();
                            //var rs = cliGet.Result;
                            //string rscontent = rs.Content.ReadAsStringAsync().Result;
    
                            //向API发送请求
                            DeliveryRecords drc = new DeliveryRecords()
                            {
                                CustCode = "001",    
                                LogisticCode = "SUER001",
                                Express = "速尔",        
                                OutNo = "abc01",        
                                Assistant = "何助理",    
                                DanQty = "1",            
                                JianQty = "13",          
                                SendDate = "2018-11-22"  
                            };
                            string rcJsonStr = JsonConvert.SerializeObject(drc);           
                            var rcContent = new FormUrlEncodedContent(new[] {
                                                                    new KeyValuePair<string, string>("__RequestVerificationToken", __RequestVerificationToken1),
                                                                    new KeyValuePair<string, string>("rcJson", rcJsonStr)
                            });
                            var cliRcPost = client.PostAsync("/warehouseapi/admin/InsertDeliRecoAsync", rcContent);
                            cliRcPost.Wait();
                            var rs = cliRcPost.Result;
                            var rsStr = rs.Content.ReadAsStringAsync().Result;
                            Console.WriteLine(rsStr);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                Console.Read();
    

      

  • 相关阅读:
    hihoCoder #1062 : 最近公共祖先·一
    hihoCoder #1050 : 树中的最长路
    hihoCoder #1049 : 后序遍历
    108 Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树
    107 Binary Tree Level Order Traversal II 二叉树的层次遍历 II
    106 Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
    105 Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树
    104 Maximum Depth of Binary Tree 二叉树的最大深度
    102 Binary Tree Level Order Traversal 二叉树的层次遍历
    101 Symmetric Tree 判断一颗二叉树是否是镜像二叉树
  • 原文地址:https://www.cnblogs.com/SasaL/p/9962113.html
Copyright © 2020-2023  润新知