最近看了一点 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 = , Name = "Tomato Soup", Category = "Groceries", Price = },
new Product { Id = , Name = "Yo-yo", Category = "Toys", Price = 3.75M },
new Product { Id = , 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="" />
<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 > )
{
base.OnActionExecuting(actionContext);
return;
} var cookie = actionContext.Request.Headers.GetCookies();
if (cookie == null || cookie.Count < )
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
return;
} FormsAuthenticationTicket ticket = null; foreach (var perCookie in cookie[].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 == "")
{
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", "", "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(';')[].Substring(cookieName.Length + );
}
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

好了到此结束。

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

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

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(3)--Idetity,OWIN前后端验证 chsakell分享了前端使用AngularJS,后端使用ASP. ...

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

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(2)--前端,以及前后端Session chsakell分享了前端使用AngularJS,后端使用ASP.NE ...

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

    原文:购物车Demo,前端使用AngularJS,后端使用ASP.NET Web API(1)--后端 chsakell分享了前端使用AngularJS,后端使用ASP.NET Web API的购物车 ...

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

    创建一个空的ASP.NET Web Form项目. 右键项目,添加新项,创建Web API控制器类,TestController. 删除掉TestController默认的内容,编写如下: using ...

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

    写在前面 HTTP RESTful 创建Web API 调用Web API 运行截图及Demo下载 ASP.NET Web API是​​一个框架,可以很容易构建达成了广泛的HTTP服务客户端,包括浏览 ...

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

    本文转自:http://www.cnblogs.com/parry/p/ASPNET_MVC_Web_API_digest_authentication.html 在前一篇文章中,主要讨论了使用HTT ...

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

    在前一篇文章中,主要讨论了使用HTTP基本认证的方法,因为HTTP基本认证的方式决定了它在安全性方面存在很大的问题,所以接下来看看另一种验证的方式:digest authentication,即摘要认 ...

  8. Authentication and Authorization in ASP.NET Web API

      You've created a web API, but now you want to control access to it. In this series of articles, we ...

  9. Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 Part 3 (by TAISEER)

    http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-an ...

随机推荐

  1. 软件工程part5

    1.本周psp 2.本周饼状图 3.本周进度条

  2. node 第一天

    在开发的过程中,几乎不可能一次性就能写出毫无破绽的程序,断点调试代码是一个普遍的需求. 作为前端开发工程师,以往我们开发的JavaScript程序都运行在浏览器端,利用Chrome提供的开发者工具就可 ...

  3. jquery计算器(改良版)

    代码: <!Doctype html> <html> <meta charset="UTF-8"> <title>计算器</t ...

  4. Spring事务管理Transaction

    Spring提供了许多内置事务管理器实现: DataSourceTransactionManager:位于org.springframework.jdbc.datasource包中,数据源事务管理器, ...

  5. [C/C++] 原码、反码、补码问题

    正确答案:D 解析: C语言中变量以补码形式存放在内存中,正数的补码与原码相同,负数求补码方式为(符号位不变,其余各位取反,最后末尾加1): 32位机器:int 32位,short 16位.  x = ...

  6. Bootstrap 轮播图的使用和理解

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...

  7. 【Python】Python中*args 和**kwargs的用法

    好久没有学习Python了,应为工作的需要,再次拾起python,唤起记忆. 当函数的参数不确定时,可以使用*args 和**kwargs,*args 没有key值,**kwargs有key值. 还是 ...

  8. 源码安装和yum安装的区别。

    yum是将yum源中别人已经编译好的rpm包下载到本地,然后安装,不需要考虑依赖,主要是方便.源码安装没法人为的控制,安装的版本也很低. 源码安装需要自己编译,安装,编译过程中可以设置参数.可安装的版 ...

  9. [ZJOI2011]最小割 & [CQOI2016]不同的最小割 分治求最小割

    题面: [ZJOI2011]最小割 [CQOI2016]不同的最小割 题解: 其实这两道是同一道题.... 最小割是用的dinic,不同的最小割是用的isap 其实都是分治求最小割 简单讲讲思路吧 就 ...

  10. BZOJ2527 & 洛谷3527:[Poi2011]Meteors——题解

    +++++++++++++++++++++++++++++++++++++++++++ +本文作者:luyouqi233. + +欢迎访问我的博客:http://www.cnblogs.com/luy ...