- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net.Http;
- using System.Threading;
- using System.Threading.Tasks;
- using System.web;
- using System.Web.Http;
- using System.Web.Http.Controllers;
- using System.Net;
- using System.Diagnostics;
- namespace Hbb0b0.MVC.CORS
- {
- /// <summary>
- /// 跨域属性
- /// 此处参考
- /// asp.net webapi 2
- ///
- /// </summary>
- public class CorsAttribute : Attribute
- {
- /// <summary>
- /// 允许的站点列表
- /// </summary>
- public Uri[] AllowOrigins
- {
- get;
- private set;
- }
- /// <summary>
- /// 错误提示
- /// </summary>
- public string ErrorMessage
- {
- get;
- set;
- }
- /// <summary>
- /// 构造函数
- /// </summary>
- /// <param name="allowOrigins"></param>
- public
- CorsAttribute(
- params string[] allowOrigins)
- {
- this
- .AllowOrigins = (allowOrigins
- new string
- [
- 0
- ]).Select(p =>
- new Uri(p)).ToArray();
- }
- /// <summary>
- /// 获取请求头信息,判断是否请求被允许跨域
- /// </summary>
- /// <param name="request"></param>
- /// <param name="headers"></param>
- /// <returns></returns>
- public bool
- TryEvaluate(HttpRequestMessage request,
- out
- IDictionary<
- string
- ,
- string
- >
- headers)
- {
- headers
- =
- null;
- string
- origin =
- request.Headers.GetValues(HttpHeaderKeys.ORIGIN).FirstOrDefault();
- Uri originUrl
- =
- new Uri(origin);
- if
- (
- this.AllowOrigins.Contains(originUrl))
- {
- headers
- =
- this.GenerateResposeHeaders(request);
- return true;
- }
- this
- .ErrorMessage =
- "Cross-origin request denied";
- return false;
- }
- /// <summary>
- /// 添加跨域许可请求头
- /// </summary>
- /// <param name="request"></param>
- /// <returns></returns>
- private
- IDictionary<
- string
- ,
- string
- >
- GenerateResposeHeaders(HttpRequestMessage request)
- {
- string
- origin = request.Headers.GetValues(
- "Origin").First();
- Dictionary
- <
- string
- ,
- string
- > headers =
- new
- Dictionary<
- string
- ,
- string
- >
- ();
- headers.Add(HttpHeaderKeys.ACCESS_CONTROL_ALLOW_ORIGIN, origin);
- if (request.IsPreflightRequest())
- {
- headers.Add(HttpHeaderKeys.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
- string
- requestHeaders =
- request.Headers.GetValues(HttpHeaderKeys.ACCESS_CONTROL_ALLOW_REQUEST_HEADERS).FirstOrDefault();
- if
- (!
- string.IsNullOrEmpty(requestHeaders))
- {
- headers.Add(HttpHeaderKeys.ACCESS_CONTROL_ALLOW_REQUEST_HEADERS, requestHeaders);
- }
- }
- return headers;
- }
- }
- /// <summary>
- /// Http Header keys
- /// </summary>
- public class HttpHeaderKeys
- {
- public const string
- ORIGIN =
- "Origin";
- public const string
- ACCESS_CONTROL_ALLOW_ORIGIN =
- "Access-Control-Allow-Origin";
- public const string
- ACCESS_CONTROL_ALLOW_REQUEST_METHOD =
- "Access-Control-Allow-Request-Methods";
- public const string
- ACCESS_CONTROL_ALLOW_REQUEST_HEADERS =
- "Access-Control-Allow-Request-Headers";
- }
- /// <summary>
- /// 判断是否是非简单跨域请求扩展方法
- /// </summary>
- public static class HttpRequestMessageExtensions
- {
- public static bool
- IsPreflightRequest(
- this HttpRequestMessage request)
- {
- return
- request.Method == HttpMethod.Options &&
- request.Headers.GetValues(HttpHeaderKeys.ORIGIN).Any()
- &&
- request.Headers.GetValues(HttpHeaderKeys.ACCESS_CONTROL_ALLOW_REQUEST_METHOD).Any();
- }
- }
- public class CorsMessageHandler : DelegatingHandler
- {
- protected override
- Task
- SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
- {
- //Debugger.Break();
- HttpMethod originalMethod
- =
- request.Method;
- bool
- isPreflightRequest =
- request.IsPreflightRequest();
- if (isPreflightRequest)
- {
- string
- method =
- request.Headers.GetValues(HttpHeaderKeys.ACCESS_CONTROL_ALLOW_REQUEST_HEADERS).FirstOrDefault();
- request.Method
- =
- new HttpMethod(method);
- }
- HttpConfiguration config
- =
- request.GetConfiguration();
- HttpControllerDescriptor description
- =
- config.Services.GetHttpControllerSelector().SelectController(request);
- HttpControllerContext context
- =
- new HttpControllerContext(request.GetConfiguration(), request.GetRouteData(), request)
- {
- ControllerDescriptor
- =
- description
- };
- HttpActionDescriptor actionDescriptor
- =
- config.Services.GetActionSelector().SelectAction(context);
- CorsAttribute corsAttribute
- = actionDescriptor.GetCustomAttributes
- ().FirstOrDefault();
- if
- (corsAttribute ==
- null)
- {
- return base.SendAsync(request, cancellationToken);
- }
- IDictionary
- <
- string
- ,
- string
- >
- headers;
- request.Method
- =
- originalMethod;
- HttpResponseMessage response
- =
- null;
- //判断请求是否被授权
- bool
- authorized = corsAttribute.TryEvaluate(request,
- out headers);
- //处理非简单跨域请求
- if (isPreflightRequest)
- {
- if (authorized)
- {
- response
- =
- new HttpResponseMessage(HttpStatusCode.OK);
- }
- }
- //简单跨域请求
- else
- {
- //如果授权,返回请求资源
- if (authorized)
- {
- response
- =
- base.SendAsync(request, cancellationToken).Result;
- }
- //非授权,返回错误信息
- else
- {
- response
- =
- request.CreateErrorResponse(HttpStatusCode.BadRequest, corsAttribute.ErrorMessage);
- }
- }
- //添加header
- if
- (headers!=
- null)
- {
- foreach
- (
- var
- item
- in headers)
- {
- response.Headers.Add(item.Key, item.Value);
- }
- }
- return
- Task.FromResult
- (response);
- }
- }
- }
来源: http://www.cnblogs.com/hbb0b0/p/7189709.html