当前位置: 首页 > 知识库问答 >
问题:

JWT和Web API(JWTAUTHFORWebAPI?)--寻找榜样

何楷
2023-03-14

我相信我已经确定了JwtAuthForWebAPI,因此使用它的示例将非常棒。

我假设任何未用[Authorize]修饰的方法都将一如既往地工作,并且如果客户端传递的令牌不匹配,任何用[Authorize]修饰的方法都将401。

我还不知道如何在初始身份验证时将令牌发送回客户端。

RegisterRoutes(GlobalConfiguration.Configuration.Routes);
var builder = new SecurityTokenBuilder();
var jwtHandler = new JwtAuthenticationMessageHandler
{
    AllowedAudience = "http://xxxx.com",
    Issuer = "corp",
    SigningToken = builder.CreateFromKey(Convert.ToBase64String(new byte[]{4,2,2,6}))
};

GlobalConfiguration.Configuration.MessageHandlers.Add(jwtHandler);

共有1个答案

祁嘉木
2023-03-14

最后,我不得不从几个不同的地方获取信息,以创建一个适合我的解决方案(实际上,是一个可行的生产解决方案的开始--但它起作用了!)

我摆脱了JwtAuthForWebAPI(尽管我确实从它借用了一部分,允许没有授权头的请求流经不受[Authorize]保护的WebAPI控制器方法)。

相反,我使用的是Microsoft的JWT库(用于Microsoft.NET Framework的JSON Web令牌处理程序-来自NuGet)。

方法如下:

[HttpPost]
public LoginResult PostSignIn([FromBody] Credentials credentials)
{
    var auth = new LoginResult() { Authenticated = false };

    if (TryLogon(credentials.UserName, credentials.Password))
    {
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.Name, credentials.UserName), 
                new Claim(ClaimTypes.Role, "Admin")
            }),

            AppliesToAddress = ConfigurationManager.AppSettings["JwtAllowedAudience"],
            TokenIssuerName = ConfigurationManager.AppSettings["JwtValidIssuer"],
            SigningCredentials = new SigningCredentials(new 
                InMemorySymmetricSecurityKey(JwtTokenValidationHandler.SymmetricKey),
                "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
                "http://www.w3.org/2001/04/xmlenc#sha256")
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var token = tokenHandler.CreateToken(tokenDescriptor);
            var tokenString = tokenHandler.WriteToken(token);

            auth.Token = tokenString;
            auth.Authenticated = true;
        }

    return auth;
}

更新

有一个关于在后续请求中处理令牌的问题。我所做的是创建一个DelegatingHandler来尝试读取/解码令牌,然后创建一个主体并将其设置为Thread.CurrentPrincipal和HttpContext.Current.User(您需要将其设置为两者)。最后,我用适当的访问限制来修饰控制器方法。

private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
{
    token = null;
    IEnumerable<string> authzHeaders;
    if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
    {
        return false;
    }
    var bearerToken = authzHeaders.ElementAt(0);
    token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
    return true;
}


protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    HttpStatusCode statusCode;
    string token;

    var authHeader = request.Headers.Authorization;
    if (authHeader == null)
    {
        // missing authorization header
        return base.SendAsync(request, cancellationToken);
    }

    if (!TryRetrieveToken(request, out token))
    {
        statusCode = HttpStatusCode.Unauthorized;
        return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode));
    }

    try
    {
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        TokenValidationParameters validationParameters =
            new TokenValidationParameters()
            {
                AllowedAudience = ConfigurationManager.AppSettings["JwtAllowedAudience"],
                ValidIssuer = ConfigurationManager.AppSettings["JwtValidIssuer"],
                SigningToken = new BinarySecretSecurityToken(SymmetricKey)
            };

        IPrincipal principal = tokenHandler.ValidateToken(token, validationParameters);
        Thread.CurrentPrincipal = principal;
        HttpContext.Current.User = principal;

        return base.SendAsync(request, cancellationToken);
    }
    catch (SecurityTokenValidationException e)
    {
        statusCode = HttpStatusCode.Unauthorized;
    }
    catch (Exception)
    {
        statusCode = HttpStatusCode.InternalServerError;
    }

    return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode));
}
public static void Start()
{
    GlobalConfiguration.Configuration.MessageHandlers.Add(new JwtTokenValidationHandler());
}
[Authorize(Roles = "OneRoleHere")]
[GET("/api/admin/settings/product/allorgs")]
[HttpGet]
public List<Org> GetAllOrganizations()
{
    return QueryableDependencies.GetMergedOrganizations().ToList();
}

[Authorize(Roles = "ADifferentRoleHere")]
[GET("/api/admin/settings/product/allorgswithapproval")]
[HttpGet]
public List<ApprovableOrg> GetAllOrganizationsWithApproval()
{
    return QueryableDependencies.GetMergedOrganizationsWithApproval().ToList();
}
 类似资料:
  • .NET Core Web API (JWT Auth) Example Get started Build & Run git clone https://github.com/GLEBR1K/webapi-jwt-example jwtcd jwt\WebAPI_Exampledotnet run Use Try to register with POST /api/register and

  • 我按照教程,但它似乎不能正常工作与JWT,但它是确定的基本身份验证。 我下载并安装了JwtAuthForWebAPI。我还生成了JWT令牌并尝试执行API调用,但错误是。 我必须实现/修改任何东西来将索赔从JWT转移到线程。当前原则 我的代码非常简单:global.asax.cs: Web.config: 调用示例

  • 问题内容: 假设我在一行中有一些随机的文本块。像这样 但是无论出于何种原因(包含元素的宽度设置,使用文本缩放等),在查看器的屏幕上它都显示为两行或更多行。 要么 有没有办法通过JavaScript找出发生换行的地方? 并返回而不管文本如何显示。 问题答案: 这就是我最终使用的(随意批评和复制以作恶用)。 首先,当编辑来自用户时,将其拆分为。 替换换行的原因是,编辑文本框中填充了,它会忽略标签,但出

  • Appium 支持 WebDriver 定位策略的子集: 通过 "class" 查找 (例如, UI 组件的类型) 通过 "xpath" 查找 (例如, 一个元素的路径以抽象的方式去表达,具有一定的约束) 你可以查看关于以上的列表,选择器策略 (English)。 Appium 还额外支持部分 Mobile JSON Wire Protocol 的定位策略。 -ios predicate stri

  • 问题内容: 我有一个问题,那个maven正在Eclipse安装文件夹中寻找资源。 这是说: 当我的工作区在内部时。 pom.xml是否有任何配置以命令它从其位置看起来是相对的? 编辑#1: 我正在从Eclipse运行Maven。从命令行可以毫无问题地进行编译。 我正在尝试运行Junit测试。 编辑2: 所有依赖项,web.xml等都可以- 我知道这是因为其他开发人员在Linux上和Idea上使用的

  • 在这些处理器上作代码优化时,分析瓶颈的原因很重要。 当有一个要害的瓶颈存在时,花时间优化不是瓶颈的方面是没有意义的。 如果你估计到指令cache失效,那么你应该重组代码,将用得最多的部分放在一起。 如果你估计有很多次数据cache失效,那么不要再想其它事情了,集中精力于重组数据减少cache失效的次数(第7章),且要避免在读数据cache失效后存在一个长的依赖环(第20章)。 如果你有很多除法,那