c# – 如何使用Web Api中的Api密钥进行使用表单身份验证的服务身份验证

我正在使用MVC 4 Web Api,我希望在使用我的服务之前对用户进行身份验证.

我已经实现了一个授权消息处理程序,它运行得很好.

public class AuthorizationHandler : DelegatingHandler
{
    private readonly AuthenticationService _authenticationService = new AuthenticationService();

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
    {
        IEnumerable<string> apiKeyHeaderValues = null;
        if (request.Headers.TryGetValues("X-ApiKey",out apiKeyHeaderValues))
        {
            var apiKeyHeaderValue = apiKeyHeaderValues.First();

            // ... your authentication logic here ...
            var user = _authenticationService.GetUserByKey(new Guid(apiKeyHeaderValue));

            if (user != null)
            {

                var userId = user.Id;

                var userIdClaim = new Claim(ClaimTypes.SerialNumber,userId.ToString());
                var identity = new ClaimsIdentity(new[] { userIdClaim },"ApiKey");
                var principal = new ClaimsPrincipal(identity);

                Thread.CurrentPrincipal = principal;
            }
        }

        return base.SendAsync(request,cancellationToken);
    }
}

问题是,我使用表单身份验证.

[HttpPost]
    public ActionResult Login(UserModel model)
    {
        if (ModelState.IsValid)
        {
            var user = _authenticationService.Login(model);
            if (user != null)
            {
                // Add the api key to the HttpResponse???
            }
            return View(model);
        }

        return View(model);
    }

当我打电话给我的时候:

[Authorize]
public class TestController : ApiController
{
    public string GetLists()
    {
        return "Weee";
    }
}

处理程序找不到X-ApiKey标头.

有没有办法将用户的api密钥添加到http响应头并保持密钥,只要用户登录
有没有其他方法来实现此功能

解决方法

我找到了以下文章 http://www.asp.net/web-api/overview/working-with-http/http-cookies
使用它我配置我的AuthorizationHandler使用cookie:
public class AuthorizationHandler : DelegatingHandler
{
    private readonly IAuthenticationService _authenticationService = new AuthenticationService();

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
    {
        var cookie = request.Headers.GetCookies(Constants.ApiKey).FirstOrDefault();
        if (cookie != null)
        {
            var apiKey = cookie[Constants.ApiKey].Value;
            try
            {
                var guidKey = Guid.Parse(apiKey);

                var user = _authenticationService.GetUserByKey(guidKey);
                if (user != null)
                {

                    var userIdClaim = new Claim(ClaimTypes.Name,apiKey);
                    var identity = new ClaimsIdentity(new[] { userIdClaim },"ApiKey");
                    var principal = new ClaimsPrincipal(identity);

                    Thread.CurrentPrincipal = principal;

                }
            }
            catch (FormatException)
            {
            }
        }

        return base.SendAsync(request,cancellationToken);
    }
}

我配置了我的登录操作结果:

[HttpPost]
    public ActionResult Login(LoginModel model)
    {
        if (ModelState.IsValid)
        {
            var user = _authenticationService.Login(model);
            if (user != null)
            {
                _cookieHelper.SetCookie(user);

                return RedirectToAction("Index","Home");
            }

            ModelState.AddModelError("","Incorrect username or password");
            return View(model);
        }

        return View(model);
    }

在里面,我使用的是我创建的CookieHelper.它由一个界面组成:

public interface ICookieHelper
{
    void SetCookie(User user);

    void RemoveCookie();

    Guid GetUserId();
}

以及实现接口的类:

public class CookieHelper : ICookieHelper
{
    private readonly HttpContextBase _httpContext;

    public CookieHelper(HttpContextBase httpContext)
    {
        _httpContext = httpContext;
    }

    public void SetCookie(User user)
    {
        var cookie = new HttpCookie(Constants.ApiKey,user.UserId.ToString())
        {
            Expires = DateTime.UtcNow.AddDays(1)
        };

        _httpContext.Response.Cookies.Add(cookie);
    }

    public void RemoveCookie()
    {
        var cookie = _httpContext.Response.Cookies[Constants.ApiKey];
        if (cookie != null)
        {
            cookie.Expires = DateTime.UtcNow.AddDays(-1);
            _httpContext.Response.Cookies.Add(cookie);
        }
    }

    public Guid GetUserId()
    {
        var cookie = _httpContext.Request.Cookies[Constants.ApiKey];
        if (cookie != null && cookie.Value != null)
        {
            return Guid.Parse(cookie.Value);
        }

        return Guid.Empty;
    }
}

通过这个配置,现在我可以使用我的ApiControllers的Authorize属性

[Authorize]
public class TestController : ApiController
{
    public string Get()
    {
        return String.Empty;
    }
}

这意味着,如果用户没有登录.他无法访问我的api并收到401错误.此外,我可以在我的代码中的任何位置检索api密钥,我将其用作用户ID,这使得它非常干净和可读.

我不认为使用cookie是最好的解决方案,因为有些用户可能已经在浏览器中禁用了它们,但目前我还没有找到更好的方法来进行授权.

相关文章

在项目中使用SharpZipLib压缩文件夹的时候,遇到如果目录较深,则压缩包中的文件夹同样比较深的问题。比...
项目需要,几十万张照片需要计算出每个照片的特征值(调用C++编写的DLL)。 业务流程:选择照片...
var array = new byte[4]; var i = Encoding.UTF8.GetBytes(100.ToString(&quot;x2&quot;));//...
其实很简单,因为Combox的Item是一个K/V的object,那么就可以把它的items转换成IEnumerable&lt;Dic...
把.net4.6安装包打包进安装程序。 关键脚本如下: 头部引用字符串对比库 !include &quot;WordFunc....
项目需求(Winform)可以批量打印某个模板,经过百度和摸索,使用iTextSharp+ZXing.NetʿreeSp...