【问题标题】:How to test Post如何测试帖子
【发布时间】:2020-05-08 03:45:21
【问题描述】:

这是一个dotnet asp core 3 react 应用程序。

我的startup.cs 看起来像这样:

public class JwtAuthentication
{
    public string SecurityKey { get; set; }
    public string ValidIssuer { get; set; }
    public string ValidAudience { get; set; }

    public SymmetricSecurityKey SymmetricSecurityKey => new SymmetricSecurityKey(Convert.FromBase64String(SecurityKey));
    public SigningCredentials SigningCredentials => new SigningCredentials(SymmetricSecurityKey, SecurityAlgorithms.HmacSha256);
}

public class ConfigureJwtBearerOptions : IPostConfigureOptions<JwtBearerOptions>
{
    private readonly IOptions<JwtAuthentication> _jwtAuthentication;

    public ConfigureJwtBearerOptions(IOptions<JwtAuthentication> jwtAuthentication)
    {
        _jwtAuthentication = jwtAuthentication ?? throw new System.ArgumentNullException(nameof(jwtAuthentication));
    }

    public void PostConfigure(string name, JwtBearerOptions options)
    {
        var jwtAuthentication = _jwtAuthentication.Value;

        options.ClaimsIssuer = jwtAuthentication.ValidIssuer;
        options.IncludeErrorDetails = true;
        options.RequireHttpsMetadata = true;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateActor = true,
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = jwtAuthentication.ValidIssuer,
            ValidAudience = jwtAuthentication.ValidAudience,
            IssuerSigningKey = jwtAuthentication.SymmetricSecurityKey,
            NameClaimType = ClaimTypes.NameIdentifier
        };
    }
}

public class Startup
{
    public IConfiguration Configuration { get; }

    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        var connectionStringOs =
           "Server=xx.xx.xx.xxIntegrated Security=false;Trusted_Connection=false;Database=Options;User Id=xx;Password=xx;Connection Timeout=60";
        var connectionStringDs =
           "Server=xx.xx.xx.x;Integrated Security=false;Trusted_Connection=false;Database=DY;User Id=xx;Password=xx";

        services.AddDbContext<OptionsDbContext>(o =>
               o.UseSqlServer(connectionStringOs));

        services.AddDbContext<DYDbContext>(o =>
               o.UseSqlServer(connectionStringDs));


        //services.AddRazorPages();
        services.AddMvc();
        services.AddMvc(option => option.EnableEndpointRouting = false);  

        services.Configure<JwtAuthentication>(Configuration.GetSection("JwtAuthentication"));
        // I use PostConfigureOptions to be able to use dependency injection for the configuration
        // For simple needs, you can set the configuration directly in AddJwtBearer()
        services.AddSingleton<IPostConfigureOptions<JwtBearerOptions>, ConfigureJwtBearerOptions>();
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                                                              .AddJwtBearer();

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    //public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    public void Configure(IApplicationBuilder app,
           //IHostingEnvironment env,
           IHostEnvironment env,
           OptionsDbContext optionsDbContext)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();

            //app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
            //{
            //    HotModuleReplacement = true
            //});
        }

        app.UseStaticFiles();

        /// Endpoint aware middleware. 
        // Middleware can use metadata from the matched endpoint.
        //app.UseCookiePolicy();
        app.UseAuthorization();
        app.UseAuthentication();


        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default", 
                template: "{controller=Home}/{action=Index}/{id:int?}");

        });
    }
}

我添加一个控制器来获取token

using System;
using System.Linq;
using System.Security.Claims;
using System.IdentityModel.Tokens.Jwt;
using System.ComponentModel.DataAnnotations;

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Authentication.JwtBearer;

using OptionsAPI.Entities;

[Route("user/[controller]")]
public class UserController : Controller
{
    private readonly IOptions<JwtAuthentication> _jwtAuthentication;

    public UserController(IOptions<JwtAuthentication> jwtAuthentication)
    {
        _jwtAuthentication = jwtAuthentication ?? throw new ArgumentNullException(nameof(jwtAuthentication));
    }

    [HttpPost]
    [AllowAnonymous]
    public IActionResult GenerateToken([FromBody]GenerateTokenModel model)
    {
        // TODO use your actual logic to validate a user
        if (model.Password != "654321")
            return BadRequest("Username or password is invalid");

        var token = new JwtSecurityToken(
            issuer: _jwtAuthentication.Value.ValidIssuer,
            audience: _jwtAuthentication.Value.ValidAudience,
            claims: new[]
            {
                // You can add more claims if you want
                new Claim(JwtRegisteredClaimNames.Sub, model.Username),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
            },
            expires: DateTime.UtcNow.AddDays(30),
            notBefore: DateTime.UtcNow,
            signingCredentials: _jwtAuthentication.Value.SigningCredentials);

        return Ok(new
        {
            token = new JwtSecurityTokenHandler().WriteToken(token)
        });
    }

    public class GenerateTokenModel
    {
        [Required]
        public string Username { get; set; }
        [Required]
        public string Password { get; set; }
    }
}

我有一个html 文件来测试这个:

<script type="text/javascript"> 
const response = await fetch("http://www.awebsite.com/user/generatetoken", {
        method: "POST",
        body: JSON.stringify({
            username: "foo@bar",
            password: "654321"
        }),
        headers: {
            "Content-Type": "application/json",
            "Accept": "application/json"
        }
    });
const json = await response.json();
const token = json.token;
console.log(token);

</script>

当我将它加载到浏览器中时,什么也没有发生。不确定如何测试调用控制器来传递 API 使用的令牌,或者该代码是否缺少将它们联系在一起的东西?

【问题讨论】:

    标签: javascript reactjs asp.net-core .net-core jwt-auth


    【解决方案1】:

    首先是使用 Fiddler 或者浏览器的开发者工具来跟踪请求并检查错误信息。但请记住,要使用 await 关键字调用函数,它必须在 async 函数中:

    async function postData(url = '', data = {}) {
    
        const response = await fetch(url, {
            method: 'POST', 
            headers: {
            'Content-Type': 'application/json',
            "Accept": "application/json"
            },
            body: JSON.stringify(data) 
        });
        return await response.json(); 
    }
    
    postData('http://www.awebsite.com/user/generatetoken', {
            username: "foo@bar",
            password: "654321"
        })
    .then((data) => {
        console.log(data.token); 
    });
    

    或使用:

    fetch('http://www.awebsite.com/user/generatetoken', {
            method: "POST",
            body: JSON.stringify({
                username: "foo@bar",
                password: "654321"
            }),
            headers: {
                "Content-Type": "application/json",
                "Accept": "application/json"
            }
    })
    .then(response => response.json()).then(data => {
           alert(data.token)
    });
    

    注意其他潜在问题,例如 CORS 。

    【讨论】:

      猜你喜欢
      • 2018-10-09
      • 2015-12-19
      • 2019-05-20
      • 2014-10-04
      • 1970-01-01
      • 1970-01-01
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多