Web.Api 上的基本令牌身份验证和授权

Basic Token authentification and authorization on Web.Api

所以我有一个调用 WebApi 方法的 MVC 应用程序。

我在MVC App上的授权是这样完成的

  public class CustomAuthorizeAttribute : AuthorizeAttribute {

        private RolesEnum _role;

        public CustomAuthorizeAttribute() {
            _role = RolesEnum.User;
        }

        public CustomAuthorizeAttribute(RolesEnum role) {
            _role = role;
        }

        protected override bool AuthorizeCore(HttpContextBase httpContext) {

            User currentUser = (User)httpContext.Session["CurrentUser"];

            if (currentUser == null) {
                return false;
            }

            if (currentUser.Role == RolesEnum.User && _role == RolesEnum.Admin) {
                return false;
            }

            return true;
        }

调用 WebApi 方法完成身份验证

[HttpPost]
    public ActionResult Login(string username, string password)
    {

        User acc = new User();
        acc.Username = username;
        acc.Password = password;
        acc = accBL.Login(acc);

        if (acc != null) {
            Session.Add("CurrentUser", acc);
            return  RedirectToAction("Index", "Project", null);
        } else {
            return View();
        }


    }

登录方法如下所示

  public User LogIn(User acc) {
            try {
                HttpClient client = new HttpClient();
                client.BaseAddress = new Uri(BASE_URL);
                client.DefaultRequestHeaders.Accept.Add(
                   new MediaTypeWithQualityHeaderValue("application/json"));
                HttpResponseMessage response = client.PostAsJsonAsync("api/Account/Login", acc).Result;

                if (response.IsSuccessStatusCode) {
                    return response.Content.ReadAsAsync<User>().Result;
                } else {
                    return null;
                }

            } catch {
                return null;
            }
        }

WebApi 方法如下所示

 [Route("api/Account/Login")]
        [HttpPost]
        public IHttpActionResult Login(User userModel) {
            User user = db.Users.Where(p => p.Username == userModel.Username && p.Password == userModel.Password).FirstOrDefault();

            if (user != null) {
                return Ok(user);
            } else {
                throw new HttpResponseException(HttpStatusCode.Unauthorized);
            }

        }

如何在 MVC 应用程序和 WebApi 服务之间建立连接。我的授权和认证在 MVC 部分有效,但我的 WebApi 服务可以在没有这个的情况下调用 authorization/authenification。如何根据我的示例保护我的 WebApi?我已经使用 MVC 和 WebApi 工作了大约 3 周,很多事情我也不是很清楚。

我是否应该在 public IHttpActionResult Login(User userModel) 中创建一个 GUID 并在每次调用方法时检查它?我如何将此 GUID 传递给 MVC 应用程序以及从 MVC 传递给 WebApi?

您可以做的是在 WebAPILogin() 方法中创建某种令牌(例如 JWT),并使用 Ok() 响应(到 MVC 应用程序)。调用您的 API 端点的用户必须发回此令牌(例如,在自定义 "Token" header 中)。您可以在 API 端点中使用的自定义 WebAPI 授权属性中验证令牌。

例如

登录端点

[Route("api/Account/Login")]
[HttpPost]
public object Login(User userModel) {
    User user = ...;
    string token = CreateTokenForUser(user);

    if (user != null) {
        // return user and token back 
        return new {User = user, Token = token};
    } else {
        throw new HttpResponseException(HttpStatusCode.Unauthorized);
    }
}

自定义身份验证过滤器

public class UserAuthAttribute : ActionFilterAttribute, IAuthenticationFilter
{

    public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        string token = null;
        IEnumerable<string> tokenHeader;
        if (context.Request.Headers.TryGetValues("Token", out tokenHeader))
            token = tokenHeader.FirstOrDefault();

        if (token != null && IsTokenValid(token)
        {
            // user has been authenticated i.e. send us a token we sent back earlier
        }
        else 
        {
            // set ErrorResult - this will result in sending a 401 Unauthorized
            context.ErrorResult = new AuthenticationFailureResult(Invalid token", context.Request);
        }
    }

}

仅允许经过身份验证的用户访问的其他端点

[Route("api/Values")]
[HttpGet]
[UserAuth]
public object GetValues() {

    // only requests with a valid token will be able to call this because of the [UserAuth] attribute
}