【问题标题】:Basic Token authentification and authorization on Web.ApiWeb.Api 中的基本 Token 认证和授权
【发布时间】:2016-09-06 22:04:00
【问题描述】:

所以我有一个调用 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 服务可以在没有任何授权/身份验证的情况下调用。根据我的示例,如何保护我的 WebApi?我已经使用 MVC 和 WebApi 工作了大约 3 周,很多事情我也不是很清楚。

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

【问题讨论】:

    标签: c# asp.net-mvc authentication asp.net-web-api authorization


    【解决方案1】:

    您可以做的是在 WebAPI Login() 方法中创建某种令牌(例如 JWT),并返回 Ok() 响应(到 MVC 应用程序)。调用您的 API 端点的用户必须将此令牌发回(例如,在自定义“令牌”标头中)。您可以在 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
    }
    

    【讨论】:

    • 我会在几个小时内测试它!谢谢你的回答!
    • 我已经接受了答案,我把你发布的一些东西做了一些修改。谢谢!
    • 很高兴听到您找到了解决方案!我发布的想法来自一个已经在运作的更大项目......
    • 是的,我所做的更改是使用 Headers 而不是内容将令牌从 api 发送到客户端,并将 UserModel 传递到内容中。
    猜你喜欢
    • 1970-01-01
    • 2014-09-24
    • 2017-01-14
    • 1970-01-01
    • 2015-03-05
    • 2018-11-27
    • 1970-01-01
    • 2015-03-02
    • 2018-07-25
    相关资源
    最近更新 更多