Asp.net Web Api 2 FORM Authentication Demo

最近看了一点 web api 2方面的书,对认证都是简单介绍了下,所以我在这里做个简单Demo,本文主要是FORM Authentication,顺带把基本认证也讲了。

Demo

一、FORM Authentication

1、新建asp.net 空项目->Web API,如下图所示:

2、先创建一个简单无认证示例:

(1)、Models文件夹下新建Product类,

    /// <summary>
    ///  产品
    /// </summary>
    public class Product
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Category { get; set; }
        public decimal Price { get; set; }
    }

(2)、Controllers文件夹下新建ProductsController类,

 public class ProductsController : ApiController
    {
        Product[] products = new Product[]
        {
            new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
            new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
            new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
        };

        public IEnumerable<Product> GetAll()
        {

            return products;
        }

        public IHttpActionResult Get(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                return NotFound();
            }
            return Ok(product);
        }

    }

(3)、创建index.html页面,前端脚本如下,

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Web API2 Studt</title>

</head>
<body>

    <div>
        <h2>All Products</h2>
        <ul id="products"></ul>
    </div>
    <div>
        <h2>Search by ID</h2>
        <input type="text" id="prodId" size="5" />
        <input type="button" value="Search" onclick="find();" />

        <p id="product" />
    </div>
    <script src="JS/jquery-2.0.3.min.js"></script>
    <script>

        var uri = ‘api/products‘;

        $(document).ready(function () {
            // Send an AJAX request
            $.getJSON(uri)
                .done(function (data) {
                    // On success, ‘data‘ contains a list of products.
                    $.each(data, function (key, item) {
                        // Add a list item for the product.
                        $(‘<li>‘, { text: formatItem(item) }).appendTo($(‘#products‘));
                    });
                }).fail(function (jqXHR, textStatus, err) {

                    if (err == ‘Forbidden‘)
                        {self.location = ‘login.html‘;}

            });
        });

        function formatItem(item) {
            return item.Name + ‘: $‘ + item.Price;
        }

        function find() {

            var id = $(‘#prodId‘).val();
            $.getJSON(uri + ‘/‘ + id)
                .done(function (data) {
                    $(‘#product‘).text(formatItem(data));
                })
                .fail(function (jqXHR, textStatus, err) {
                    $(‘#product‘).text(‘Error: ‘ + err);
                });
        }

    </script>
</body>
</html>

(4) index.html设为起始页,启动后访问成功,

3、添加FORM Authentication认证, 

(1)、Controllers文件夹下新建FormAuth类,

using System;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;
using System.Web.Security;

namespace WebApi2Demo.Controllers
{
     [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class FormAuth : ActionFilterAttribute
    {
         public override void OnActionExecuting(HttpActionContext actionContext)
         {
             try
             {
                 if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Count > 0)
                 {
                     base.OnActionExecuting(actionContext);
                     return;
                 }

                 var cookie = actionContext.Request.Headers.GetCookies();
                 if (cookie == null || cookie.Count < 1)
                 {
                     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
                     return;
                 }

                 FormsAuthenticationTicket ticket = null;

                 foreach (var perCookie in cookie[0].Cookies)
                 {
                     if (perCookie.Name == FormsAuthentication.FormsCookieName)
                     {
                         ticket = FormsAuthentication.Decrypt(perCookie.Value);
                         break;
                     }
                 }

                 if (ticket == null)
                 {
                     actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
                     return;
                 }

                 // TODO: 添加其它验证方法

                 base.OnActionExecuting(actionContext);
             }
             catch
             {
                 actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
             }
         }

    }
}

(2)、将FormAuth特性添加到ProductsController类上面,如下图:

(3)、编译网站后,刷新index.html页面,跳转到了login.html(需要新建)页面,

看看前端js,

如果错误提示“Forbidden”,则跳转到login.html页面,这正是FormAuth中响应的HttpStatusCode(Forbidden = 403),

用Fiddler2看看,

  (4)、添加登陆认证,

1)、 新建LogOn类,

 public class LogOn
    {

        public string Username { get; set; }

        public string Password { get; set; }
    }

2)、新建登陆认证类,

  public class AccountController : ApiController
    {
        [HttpPost]
        public HttpResponseMessage Post(LogOn model)
        {

            string password;
            if (model.Username == "zzhi")
            {
                if (model.Password == "12345")
                {
                    FormsAuthentication.SetAuthCookie(model.Username, false);
                    return Request.CreateResponse(HttpStatusCode.OK, "Success");
                }
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Invalid username or password.");
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Invalid username or password.");
            }
        }

    }

3)、login.html 脚本如下,

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>登陆</title>
    <script src="JS/jquery-2.0.3.min.js"></script>
    <script>
        var uri = ‘api/Account‘;

        function login() {

            var username = $("#username").val();
            var password = $("#password").val();

            $.post(uri, { Username: username, Password: password })
              .success(function (result) {
                  alert(result);
                  window.location.href = "index.html";
              })
              .fail(function (XMLHttpRequest, textStatus, err) {
                  alert(XMLHttpRequest.status);
                  alert(XMLHttpRequest.text);
                  alert(err);
                  this.reload();
              });

        }

    </script>
</head>
<body>
    <label>用户名</label><input id="username" type="text" />
    <br />
    <label>密&nbsp;&nbsp;码</label><input id="password" type="password" />
    <br />
    <button onclick="login()">登陆</button>
</body>
</html>

编译网站后刷新login.html,输入用户名:zzhi,密码:12345,提示登陆成功,然后跳转到index.html页面。

TEST:关闭网页,再次启动网站,直接进入index.html页面并请求数据成功,fiddler2看看,

(5)、控制台访问API 2,代码如下:

  internal class Program
    {
        private static void Main(string[] args)
        {
            Process();

            Console.Read();

        }

        private static async void Process()
        {
            string token = GetSecurityToken("zzhi", "12345", "http://localhost:45690/api/Account", ".ASPXAUTH");
            string address = "http://localhost:45690/api/products";
            if (!string.IsNullOrEmpty(token))
            {
                HttpClientHandler handler = new HttpClientHandler {CookieContainer = new CookieContainer()};
                handler.CookieContainer.Add(new Uri(address), new Cookie(".ASPXAUTH", token));
                using (HttpClient httpClient = new HttpClient(handler))
                {
                    HttpResponseMessage response = httpClient.GetAsync(address).Result;
                    IEnumerable<Product> Products = await  response.Content.ReadAsAsync<IEnumerable<Product>>();

                    foreach (Product c in Products)
                    {
                        Console.WriteLine(c.Name);
                    }
                }

            }
        }

        private static string GetSecurityToken(string userName, string password, string url, string cookieName)
        {

            using (HttpClient httpClient = new HttpClient())
            {
                Dictionary<string, string> credential = new Dictionary<string, string>();
                credential.Add("Username", userName);
                credential.Add("Password", password);
                HttpResponseMessage response = httpClient.PostAsync(url, new FormUrlEncodedContent(credential)).Result;
                IEnumerable<string> cookies;
                if (response.Headers.TryGetValues("Set-Cookie", out cookies))
                {
                    string token = cookies.FirstOrDefault(value => value.StartsWith(cookieName));
                    if (null == token)
                    {
                        return null;
                    }
                    return token.Split(‘;‘)[0].Substring(cookieName.Length + 1);
                }
                return null;
            }
        }
    }

(6)、跨域访问

1)、在web项目中(我的web项目名字:WebApi2Demo)通过Nuget添加 web api 2 corss-Origin 引用,如下图:

2)、WebApiConfig.cs 配置如下:

 var cors = new EnableCorsAttribute("*", "*", "*");//跨域访问
            config.EnableCors(cors);

            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

3)、ProductsController.cs 去掉[FormAuth]特性。

ASP.net里面的Form认证,是通过在Cookie写入登陆信息,然后浏览器发送请求后服务端再去验证Cookie是否存在,从而达到认证用户的目的。但是我们现在涉及到一个跨域的问题,而Cookie是不能跨站共享的。即使RESTful那边设置了cookie,也不会到当前请求的域下面。到了第二次请求的时候,还是得不到认证信息。

这里我做了个简单测试,如果你不注释[FormAuth]特性,跨域是请求不到数据的。

那么如何跨域认证呢,一种简单方式是基本认证。

可以通过Demo中的WebCorsTest项目进行测试。

 二、基本认证,基本认证放在Demo中了,不再赘述。

Demo

相关链接RESTful api跨域认证

 Api 2 资料:

ASP.NET Web API 2 Recipes_ A Problem-Solution Approach.pdf

ASP.NET Web API 2_ Building a REST Service from Start to Finish.pdf

Pro ASP.NET Web API HTTP Web Services in ASP.NET.pdf

inside-asp-ney-web-api-2.pdf

好了到此结束。

时间: 2024-10-08 19:36:16

Asp.net Web Api 2 FORM Authentication Demo的相关文章

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证

原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证 chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解. 文章:http://chsakell.com/2015/01/31/angularjs-feat-web-api/http://chsakell.com/2015/03/07/angularjs-feat-web-api-

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session

原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解. 文章:http://chsakell.com/2015/01/31/angularjs-feat-web-api/http://chsakell.com/2015/03/07/angularjs-feat-web-api-en

购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端

原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端 chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车案例,非常精彩,这里这里记录下对此项目的理解. 文章:http://chsakell.com/2015/01/31/angularjs-feat-web-api/http://chsakell.com/2015/03/07/angularjs-feat-web-api-enable-session-

ASP.NET Web API实践系列01,以ASP.NET Web Form方式寄宿

创建一个空的ASP.NET Web Form项目. 右键项目,添加新项,创建Web API控制器类,TestController. 删除掉TestController默认的内容,编写如下: using System.Web.Http; namespace WebApplication1 { public class TestController : ApiController { [AcceptVerbs("Get")] public string SayHello() { retur

ASP.NET Web API(三):安全验证之使用摘要认证(digest authentication)

在前一篇文章中,主要讨论了使用HTTP基本认证的方法,因为HTTP基本认证的方式决定了它在安全性方面存在很大的问题,所以接下来看看另一种验证的方式:digest authentication,即摘要认证. 系列文章列表 ASP.NET Web API(一):使用初探,GET和POST数据ASP.NET Web API(二):安全验证之使用HTTP基本认证ASP.NET Web API(三):安全验证之使用摘要认证(digest authentication) 摘要认证原理 在基本认证的方式中,主

初试ASP.NET Web API/MVC API(附Demo)

参考页面: http://www.yuanjiaocheng.net/webapi/media-formatter.html http://www.yuanjiaocheng.net/webapi/webapi-filters.html http://www.yuanjiaocheng.net/webapi/create-crud-api-1.html http://www.yuanjiaocheng.net/webapi/create-crud-api-1-get.html http://ww

Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1

http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/ Currently our API doesn’t support authentication and authorization, all the requests we receive to any end point are done anonymously, I

(转)【ASP.NET Web API】Authentication with OWIN

概述 本文说明了如何使用 OWIN 来实现 ASP.NET Web API 的验证功能,以及在客户端与服务器的交互过程中,避免重复提交用户名和密码的机制. 客户端可以分为两类: JavaScript:可以理解为网页 Native:包括手机 app.windows 客户端等等 步骤 通过用户名和密码,获取 access token,请参考:http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owi

对一个前端AngularJS,后端OData,ASP.NET Web API案例的理解

依然chsakell,他写了一篇前端AngularJS,后端OData,ASP.NET Web API的Demo,关于OData在ASP.NET Web API中的正删改查没有什么特别之处,但在前端调用API时,把各种调用使用$resouce封装在一个服务中的写法颇有借鉴意义. 文章:http://chsakell.com/2015/04/04/asp-net-web-api-feat-odata/源码:https://github.com/chsakell/odatawebapi 首先是领域模