【问题标题】:How to integrate JWT authentication with Web API?如何将 JWT 身份验证与 Web API 集成?
【发布时间】:2017-03-16 07:35:31
【问题描述】:

我在将 JWT 与我的 Web API 集成时遇到问题。我尝试关注 tutorialexample

这看起来很简单,但我在将它与我的项目集成时遇到了困难。您应该知道,我有一堆 .aspx(Web 表单)文件来制作我的网站。该网站使用 javascript (Ajax) 使用我的 Web API。我已经安装了 jose-jwt 包,所以我可以在我的代码中使用它。

服务器端

WebApiConfig.cs:

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "defaultApiRoutes",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional },
                constraints: new { id = @"\d+" }   // Only matches if "id" is one or more digits.
            );

            config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

        }
    }

我在“请求”控制器中的一项操作示例:

[HttpPost]
        [ActionName("createRequest")]
        public IHttpActionResult createRequest(Request request)
        {
            if (userIsAuthorized) // I am guessing that for each action there will be this kinda condition to check the token of the user
            if (ModelState.IsValid) {
                using (SqlConnection connection = WebApiApplication.reqeustConnection("ConStrMRR")) {
                    using (SqlCommand command = new SqlCommand("createRequest", connection)) {
                        try {
                            command.CommandType = CommandType.StoredProcedure;
                            command.Parameters.Add(new SqlParameter("@status_id", request.StatusID));
                            command.Parameters.Add(new SqlParameter("@patient_firstname", request.PatientFirstName));
                            command.Parameters.Add(new SqlParameter("@patient_lastname", request.PatientLastName));
                            command.Parameters.Add(new SqlParameter("@patient_url", request.PatientURL));
                            command.Parameters.Add(new SqlParameter("@facility", request.Facility));
                            connection.Open();
                            int request_id = (int)command.ExecuteScalar();
                            return Ok(request_id);
                        } catch (Exception e) {
                            throw e;
                        } finally {
                            connection.Close();
                        }
                    }
                }
            }
            return Content(HttpStatusCode.BadRequest, "Request has not been created.");
        }

客户端

创建-request.js

$.ajax({
            url: "http://" + window.myLocalVar + "/api/requests/createRequest",
            type: "POST",
            dataType: 'json',
            contentType: 'application/json',
            data: request,
            success: function (request_id, state) {
                    console.log(request_id);
            },
            error: function (err) {
                if (err) {
                    notyMessage(err.responseJSON, 'error');
                }
            }
        });      

我猜之前的请求会在'success'函数之后更新为如下:

beforeSend: function(xhr)
              {
                xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem('token'));
              },

我的登录页面如下:

<body id="cover">

<div class="container">
    <div class="row">
        <div class="col-md-4 col-md-offset-4">
            <div class="login-panel panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">Please Sign In</h3>
                </div>
                <div class="panel-body">
                    <div align="center" style="margin-bottom: 50px;"><img class="img-responsive" src="../img/logo.jpg"/></div>
                    <form role="form" runat="server">
                        <fieldset>
                            <div class="form-group">
                                <asp:TextBox ID="usernameTextBox" CssClass="form-control" runat="server" placeholder="Username"></asp:TextBox>
                            </div>
                            <div class="form-group">
                                <asp:TextBox ID="passwordTextBox" CssClass="form-control" runat="server" placeholder="Password" TextMode="Password"></asp:TextBox>
                            </div>
                            <div class="checkbox">
                                <label>
                                    <asp:CheckBox ID="rememberMeCheckBox" runat="server"/>Remember Me
                                </label>
                            </div>
                            <!-- Change this to a button or input when using this as a form -->
                            <asp:Button CssClass="btn btn-primary btn-block" Text="Login" ID="Login" runat="server"/>
                        </fieldset>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>

我在将 JWT 身份验证与我的代码集成时遇到了困难。你能帮忙吗?

谢谢!

【问题讨论】:

  • 在进行冗长的回复之前,我想知道您要解决的场景类型。最大的问题是“你为什么要尝试使用 JWT 身份验证?”。相关问题:您的 Web api 是否仅由您自己的应用程序使用,还是您期待来自第三方客户端的调用?您是否将会话 cookie 用于您网站的网络表单部分? JWT 身份验证通常用于单页应用程序,但如果您的常规 Web 应用程序中已经存在会话 cookie,则可以使用相同的机制进行 API 调用,而不必担心 JWT。
  • @Nico,这里不会有第三方。场景是我构建了一个简单的 API 并使用网页使用它。我正在使用普通的 Jquery/Ajax 来使用 API。我在 Azure 机器上有一个活动目录。我想知道的是如何对来自 DC 的用户进行身份验证,如果用户经过验证,那么该用户将拥有一个令牌,她/他可以在向 API 发出请求时使用该令牌。所以第一件事是在为了向 API 发出请求,否则请求将被拒绝。我没有使用 cookie 或会话。
  • 正如我之前提到的,我通过 View (Ajax) 使用我的 API,我想在每个请求中传递令牌并让后端验证它。老实说,我不确定 API 是否应该验证令牌,或者 Azure 是否已经为此目的实现了某些东西。
  • 对我来说,下一步是检查用户是否可以根据他/她的角色执行请求,也从 DC 中检索到。因此,如果使用经过身份验证,则返回一个令牌和一个角色并保存它们(比如说在本地存储中或在我的网站上可访问的某个地方。)
  • 那么,Web API 将使用 ASP.Net Web API 在与作为客户端的 Web 窗体应用程序完全分离的服务器/应用程序中实现,对吧?

标签: javascript c# asp.net jwt


【解决方案1】:

所以,你将拥有:

  1. 一个 Web API 服务器(“API”)
  2. 一个 Web 表单应用程序(“客户端”)

Web API 服务器

API 将受 JWT 保护。 API 的每个客户端都应在 HTTP 标头中提供 JWT(不记名令牌)。此 JWT 将在身份验证时由身份提供者提供。

Web API 需要某种中间件来从请求中获取 JWT 令牌,对其进行验证(验证受众、颁发者、过期和签名)并设置对请求有效的 ClaimsPrincipal。这样您就可以使用 .Net 标准授权属性和程序,例如:

[Authorize] // requires the user to be authenticated
public IActionResult SomeProtectedAction()
{
}

如果您的 Web API 用于 ASP.Net Core,您可以使用 Microsoft.AspNetCore.Authentication.JwtBearer 来执行此操作,配置如下:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    var options = new JwtBearerOptions
    {
        Audience = "[Your API ID]",
        Authority = $"[URL for your identity provider]/",
        // certificate public keys will be read automatically from
        // the identity provider if possible
        // If using symmetric keys, you will have to provide them
    };
    app.UseJwtBearerAuthentication(options);

}

带有 OWIN 的常规 ASP.Net 应用程序可以使用 Microsoft.Owin.Security.ActiveDirectory 包,配置代码如下:

public void Configuration(IAppBuilder app)
{
    var issuer = $"[url to identity provider]/";
    var audience = "[your API id];

    app.UseActiveDirectoryFederationServicesBearerAuthentication(
        new ActiveDirectoryFederationServicesBearerAuthenticationOptions
        {
            TokenValidationParameters = new TokenValidationParameters
            {
                ValidAudience = audience,
                ValidIssuer = issuer
                // you will also have to configure the keys/certificates
            }
        });

客户

您的客户端应用程序将是一个网络表单应用程序。用户登录后(通常通过将用户重定向到身份提供者的登录页面),您将获得一个访问令牌。您可以将令牌存储在客户端(本地存储)中,并在调用 API 时使用它:

beforeSend: function(xhr) {
    xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem('token'));
},

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-30
    • 2018-07-13
    • 2016-04-24
    • 2017-03-09
    • 2018-01-28
    相关资源
    最近更新 更多