Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在ASP.NET内核中使用JWT(Authorization:Bearer)_C#_Asp.net Core_Swagger_Jwt - Fatal编程技术网

C# 在ASP.NET内核中使用JWT(Authorization:Bearer)

C# 在ASP.NET内核中使用JWT(Authorization:Bearer),c#,asp.net-core,swagger,jwt,C#,Asp.net Core,Swagger,Jwt,我正在ASP.NETCore1.0中创建RESTAPI。我曾使用Swagger进行测试,但现在我添加了一些路由的JWT授权。(通过使用jwtbearerauthentication) 是否可以修改Swagger请求的标题,以便测试带有[Authorize]属性的路由?我也遇到了同样的问题,并在这篇博客文章中找到了一个可行的解决方案: 归结起来,就是在配置选项中添加此选项 services.ConfigureSwaggerGen(options => { options.Operat

我正在ASP.NETCore1.0中创建RESTAPI。我曾使用Swagger进行测试,但现在我添加了一些路由的JWT授权。(通过
使用jwtbearerauthentication


是否可以修改Swagger请求的标题,以便测试带有
[Authorize]
属性的路由?

我也遇到了同样的问题,并在这篇博客文章中找到了一个可行的解决方案:

归结起来,就是在配置选项中添加此选项

services.ConfigureSwaggerGen(options =>
{
   options.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
});
services.ConfigureSwaggerGen(选项=>
{
options.OperationFilter();
});
以及操作过滤器的代码

public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
   public void Apply(Operation operation, OperationFilterContext context)
   {
      var filterPipeline = context.ApiDescription.ActionDescriptor.FilterDescriptors;
      var isAuthorized = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
      var allowAnonymous = filterPipeline.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);

      if (isAuthorized && !allowAnonymous)
      {
          if (operation.Parameters == null)
             operation.Parameters = new List<IParameter>();

          operation.Parameters.Add(new NonBodyParameter
          {                    
             Name = "Authorization",
             In = "header",
             Description = "access token",
             Required = true,
             Type = "string"
         });
      }
   }
}
公共类授权HeaderParameterOperationFilter:IOperationFilter
{
公共无效应用(操作,操作筛选器上下文)
{
var filterPipeline=context.apisdescription.ActionDescriptor.FilterDescriptors;
var isAuthorized=filterPipeline.Select(filterInfo=>filterInfo.Filter).Any(Filter=>Filter为AuthorizeFilter);
var allowAnonymous=filterPipeline.Select(filterInfo=>filterInfo.Filter).Any(Filter=>Filter为IAllowAnonymousFilter);
如果(未授权&&!禁止使用)
{
if(operation.Parameters==null)
operation.Parameters=newlist();
operation.Parameters.Add(新的非主体参数
{                    
Name=“授权”,
In=“header”,
Description=“访问令牌”,
必需=真,
Type=“string”
});
}
}
}

然后,您将在您的招摇过市中看到一个额外的授权文本框,您可以在其中以“Bearer{jwttoken}”的格式添加您的令牌,并且您应该在您的招摇过市请求中获得授权。

要扩展对我有用的HansVG答案(谢谢),由于我没有足够的贡献点,我无法直接回答Emseeta问题。一旦您有了授权文本框,您将需要调用生成令牌的端点,该令牌将位于端点的必须[授权]区域之外


调用该端点以从该端点生成令牌后,可以将其从该端点的结果中复制出来。然后您就有了令牌,可以在您必须[授权]的其他区域中使用。只需将其粘贴到文本框中。正如HansVG提到的,确保以正确的格式添加它,其中需要包括“bearer”。Format=“bearer{token}”。

目前,Swagger具有使用JWT token进行身份验证的功能,可以自动将令牌添加到头中(我使用的是Swashback.AspNetCore 1.1.0)

下面的代码应该有助于实现这一点

在Startup.ConfigureServices()中:

services.AddSwaggerGen(c =>
{
    // Your custom configuration
    c.SwaggerDoc("v1", new Info { Title = "My API", Version = "v1" });
    c.DescribeAllEnumsAsStrings();
    // JWT-token authentication by password
    c.AddSecurityDefinition("oauth2", new OAuth2Scheme
    {
        Type = "oauth2",
        Flow = "password",
        TokenUrl = Path.Combine(HostingEnvironment.WebRootPath, "/token"),
        // Optional scopes
        //Scopes = new Dictionary<string, string>
        //{
        //    { "api-name", "my api" },
        //}
    });
});
app.UseSwagger();
app.UseSwaggerUI(c =>
{
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "API V1");

    // Provide client ID, client secret, realm and application name (if need)

    // Swashbuckle.AspNetCore 4.0.1
    c.OAuthClientId("swagger-ui");
    c.OAuthClientSecret("swagger-ui-secret");
    c.OAuthRealm("swagger-ui-realm");
    c.OAuthAppName("Swagger UI");

    // Swashbuckle.AspNetCore 1.1.0
    // c.ConfigureOAuth2("swagger-ui", "swagger-ui-secret", "swagger-ui-realm", "Swagger UI");
});
如果您的令牌身份验证端点遵循OAuth2标准,那么所有这些都应该可以工作。但为了以防万一,我添加了此端点的示例:

public class AccountController : Controller
{
    [ProducesResponseType(typeof(AccessTokens), (int)HttpStatusCode.OK)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.Unauthorized)]
    [HttpPost("/token")]
    public async Task<IActionResult> Token([FromForm] LoginModel loginModel)
    {
        switch (loginModel.grant_type)
        {
            case "password":
                var accessTokens = // Authentication logic
                if (accessTokens == null)
                    return BadRequest("Invalid user name or password.");
                return new ObjectResult(accessTokens);

            case "refresh_token":
                var accessTokens = // Refresh token logic
                if (accessTokens == null)
                    return Unauthorized();
                return new ObjectResult(accessTokens);

            default:
                return BadRequest("Unsupported grant type");
        }
    }
}

public class LoginModel
{
    [Required]
    public string grant_type { get; set; }

    public string username { get; set; }
    public string password { get; set; }
    public string refresh_token { get; set; }
    // Optional
    //public string scope { get; set; }
}

public class AccessTokens
{
    public string access_token { get; set; }
    public string refresh_token { get; set; }
    public string token_type { get; set; }
    public int expires_in { get; set; }
}
公共类AccountController:控制器
{
[产品响应类型(类型为(AccessTokens),(int)HttpStatusCode.OK)]
[产品响应类型((int)HttpStatusCode.BadRequest)]
[产品响应类型((int)HttpStatusCode.Unauthorized)]
[HttpPost(“/token”)]
公共异步任务令牌([FromForm]LoginModel LoginModel)
{
开关(loginModel.grant\u类型)
{
案例“密码”:
var accessTokens=//身份验证逻辑
if(accessTokens==null)
返回错误请求(“无效用户名或密码”);
返回新的ObjectResult(accessTokens);
案例“刷新令牌”:
var accessTokens=//刷新令牌逻辑
if(accessTokens==null)
未经授权返回();
返回新的ObjectResult(accessTokens);
违约:
返回错误请求(“不支持的授权类型”);
}
}
}
公共类登录模型
{
[必需]
公共字符串grant_type{get;set;}
公共字符串用户名{get;set;}
公共字符串密码{get;set;}
公共字符串刷新\u标记{get;set;}
//可选的
//公共字符串作用域{get;set;}
}
公共类访问令牌
{
公共字符串访问\u令牌{get;set;}
公共字符串刷新\u标记{get;set;}
公共字符串标记\u类型{get;set;}
{get;set;}中的公共int过期
}
多亏了,这就是我最终用Swagger 4.0.1在ASP.NET Core 2.2中解决此问题的方法

在Startup.cs ConfigureServices()中:

下面是我如何创建一个端点来分发JWT令牌:

[ApiController, Route("[controller]")]
public class TokenController : ControllerBase
{
    [HttpPost, AllowAnonymous]
    public async Task<ActionResult<AccessTokensResponse>> RequestToken([FromForm]LoginRequest request)
    {
        var claims = await ValidateCredentialAndGenerateClaims(request);

        var now = DateTime.UtcNow;
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_setting.SecurityKey));
        var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            issuer: _setting.Issuer,
            audience: _setting.Audience,
            claims: claims,
            notBefore: now,
            expires: now.AddMinutes(_setting.ValidDurationInMinute),
            signingCredentials: signingCredentials);

        return Ok(new AccessTokensResponse(token));
    }
}

您可以使用以下命令添加带有API调用的任何附加头

//注册招摇过市生成器,定义一个或多个招摇过市文档
services.AddSwaggerGen(c=>
{
c、 大摇大摆的文件(“v1”,新信息
{
Version=“v1”,
Title=“核心API”,
Description=“ASP.NET核心API”,
TermsOfService=“无”,
联系人=新联系人
{
Name=“Raj Kumar”,
Email=“”
},
许可证=新许可证
{
Name=“演示”
}
});
c、 AddSecurityDefinition(“持有人”,新ApiKeyScheme()
{
Description=“使用承载方案的JWT授权头。示例:\“授权:承载{token}\”,
Name=“授权”,
In=“header”,
Type=“apiKey”
});
c、 AddSecurityRequest(新字典)
{
{“Bearer”,新字符串[]{}
});
});

我还将检查授权属性

var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;

var hasAuthorizedFilter = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
var hasAuthorizedAttribute = context.MethodInfo.ReflectedType?.CustomAttributes.First().AttributeType ==
                                     typeof(AuthorizeAttribute);

if ((hasAuthorizedFilter || hasAuthorizedAttribute) && !allowAnonymous)
{
    var oAuthScheme = new OpenApiSecurityScheme
    {
        Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
    };

    operation.Security = new List<OpenApiSecurityRequirement>
    {
        new OpenApiSecurityRequirement
        {
            [ oAuthScheme ] = new List<string>()
        }
    };
}

我将招摇过市与firebase相结合

使用swagger ui中的试用功能时,您从何处获得要放入jwttoken字段的承载令牌?只是一个快速帮助;使用Microsoft.AspNetCore.Mvc.Authorization;使用swashback.AspNetCore.Swagger;使用swashback.AspNetCore.SwaggerGen;使用System.Collections.Generic;使用System.Linq;我们如何自动分配持票人
[ApiController, Route("[controller]")]
public class TokenController : ControllerBase
{
    [HttpPost, AllowAnonymous]
    public async Task<ActionResult<AccessTokensResponse>> RequestToken([FromForm]LoginRequest request)
    {
        var claims = await ValidateCredentialAndGenerateClaims(request);

        var now = DateTime.UtcNow;
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_setting.SecurityKey));
        var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        var token = new JwtSecurityToken(
            issuer: _setting.Issuer,
            audience: _setting.Audience,
            claims: claims,
            notBefore: now,
            expires: now.AddMinutes(_setting.ValidDurationInMinute),
            signingCredentials: signingCredentials);

        return Ok(new AccessTokensResponse(token));
    }
}
/// <summary>
/// Encapsulates fields for login request.
/// </summary>
/// <remarks>
/// See: https://www.oauth.com/oauth2-servers/access-tokens/
/// </remarks>
public class LoginRequest
{
    [Required]
    public string grant_type { get; set; }
    public string username { get; set; }
    public string password { get; set; }
    public string refresh_token { get; set; }
    public string scope { get; set; }

    public string client_id { get; set; }
    public string client_secret { get; set; }
}

/// <summary>
/// JWT successful response.
/// </summary>
/// <remarks>
/// See: https://www.oauth.com/oauth2-servers/access-tokens/access-token-response/
/// </remarks>
public class AccessTokensResponse
{
    /// <summary>
    /// Initializes a new instance of <seealso cref="AccessTokensResponse"/>.
    /// </summary>
    /// <param name="securityToken"></param>
    public AccessTokensResponse(JwtSecurityToken securityToken)
    {
        access_token = new JwtSecurityTokenHandler().WriteToken(securityToken);
        token_type = "Bearer";
        expires_in = Math.Truncate((securityToken.ValidTo - DateTime.UtcNow).TotalSeconds);
    }

    public string access_token { get; set; }
    public string refresh_token { get; set; }
    public string token_type { get; set; }
    public double expires_in { get; set; }
}
// Register the Swagger generator, defining 1 or more Swagger documents
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info
    {
        Version = "v1",
        Title = "Core API",
        Description = "ASP.NET Core API",
        TermsOfService = "None",
        Contact = new Contact
        {
            Name = "Raj Kumar",
            Email = ""
        },
        License = new License
        {
            Name = "Demo"
        }
    });
    c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
    {
        Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
        Name = "Authorization",
        In = "header",
        Type = "apiKey"
    });
    c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
    {
    {"Bearer",new string[]{}}
    });
});
var filterDescriptor = context.ApiDescription.ActionDescriptor.FilterDescriptors;

var hasAuthorizedFilter = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is AuthorizeFilter);
var allowAnonymous = filterDescriptor.Select(filterInfo => filterInfo.Filter).Any(filter => filter is IAllowAnonymousFilter);
var hasAuthorizedAttribute = context.MethodInfo.ReflectedType?.CustomAttributes.First().AttributeType ==
                                     typeof(AuthorizeAttribute);

if ((hasAuthorizedFilter || hasAuthorizedAttribute) && !allowAnonymous)
{
    var oAuthScheme = new OpenApiSecurityScheme
    {
        Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
    };

    operation.Security = new List<OpenApiSecurityRequirement>
    {
        new OpenApiSecurityRequirement
        {
            [ oAuthScheme ] = new List<string>()
        }
    };
}
[Authorize(Policy = AppConfiguration.PermissionReadWrite)]
[Route("api/[controller]")]
[ApiController]
public class FooController : ControllerBase
{
   ...
}