无法使用Postman从数据库获取数据,但是POST可以正常工作

时间:2019-06-09 16:11:55

标签: c# angular

我能够使用POST成功获取新令牌,但是当使用新令牌并将其应用于Bearer值以从Sqlite获取数据时,出现错误。我试图问一些专家,但是他们告诉我他们没有发现我的代码有什么问题。这是Sqlite数据库问题吗?可以切换到SQL Server来解决此问题吗? AddJwtBearer代码有问题吗?我不知道该项目是否可以在另一台计算机上工作。是什么原因导致此问题?

info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[7]
      Bearer was not authenticated. Failure message: IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey , KeyId:
      '.
Exceptions caught:
 ''.
token: '{"alg":"HS256","typ":"JWT"}.{"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":"2","http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name":"georgia","exp":1560096782,"iss":"http://localhost:5000","aud":"http://localhost:5000"}'.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Route matched with {action = "GetUsers", controller = "Users"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] GetUsers() on controller DatingApp.API.Controllers.UsersController (DatingApp.API).
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
      AuthenticationScheme: Bearer was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action DatingApp.API.Controllers.UsersController.GetUsers (DatingApp.API) in 0.2098ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 2.6942ms 401

Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DatingApp.API.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; //6.1.0
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.EntityFrameworkCore; //ONLY 2.1.0 works
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.Net;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using DatingApp.API.Helpers;
using AutoMapper;

namespace DatingApp.API
{
public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<DataContext>(x => x.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); //here
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
            .AddJsonOptions(opt => {
                opt.SerializerSettings.ReferenceLoopHandling = 
                Newtonsoft.Json.ReferenceLoopHandling.Ignore; //For loop error
            });            
        //services.AddCors(); //add this  
        services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
            builder => builder.AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials()
            .Build());
        });
        services.Configure<CloudinarySettings>(Configuration.GetSection("CloudinarySettings"));
        services.AddAutoMapper(typeof(Startup)); //using 6.1.0 check csproj file
        services.AddTransient<Seed>(); //JSON config
        services.AddScoped<IAuthRepository, AuthRepository>(); //add controllers
        services.AddScoped<IDatingRepository, DatingRepository>();
        //services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        services.AddAuthentication(o => {o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        o.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;})        
        .AddJwtBearer(options => {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
                .GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, Seed seeder)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler(builder => {
                builder.Run(async context => {
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

                    var error = context.Features.Get<IExceptionHandlerFeature>();
                    if (error != null)
                    {
                        context.Response.AddApplicationError(error.Error.Message);
                        await context.Response.WriteAsync(error.Error.Message);
                    }
                });
            });
            //app.UseHsts();
        }

        //app.UseHttpsRedirection();
        //seeder.SeedUsers();
        //app.UseCors(x => x.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials()); //add this
        app.UseCors("CorsPolicy");
        app.UseAuthentication();
        app.UseMvc(); //add this
    }
}
}

appsettings.json

{
  "AppSettings": {
    "Token": "super secret key"
  },
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=DatingApp.db"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  }
}

AuthController.cs

using System;
using System.IdentityModel.Tokens.Jwt; //here
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using DatingApp.API.Data;
using DatingApp.API.Dtos;
using DatingApp.API.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens; //Symmetric Security Keys

namespace DatingApp.API.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AuthController : ControllerBase
    {
        private readonly IAuthRepository _repo;
        private readonly IConfiguration _config;
        public AuthController(IAuthRepository repo, IConfiguration config)
        {
            _config = config;
            _repo = repo;
        }

        [HttpPost("register")]
        public async Task<IActionResult> Register(UserForRegisterDto userForRegisterDto) //get username and password, [FromBody] gives hint where info is
        {
            userForRegisterDto.Username = userForRegisterDto.Username.ToLower(); //make username lowercase

            if (await _repo.UserExists(userForRegisterDto.Username)) //check if User exist
                return BadRequest("Username already exist"); //BadRequist requires ControllerBase

            var userToCreate = new User
            {
                Username = userForRegisterDto.Username //APIModels
            };

            var createdUser = await _repo.Register(userToCreate, userForRegisterDto.Password);

            return StatusCode(201);
        }

        [HttpPost("login")]
        public async Task<IActionResult> Login(UserForLoginDto userForLoginDto)
        {
            var userFromRepo = await _repo.Login(userForLoginDto.Username.ToLower(), userForLoginDto.Password);

            if (userFromRepo == null)
                return Unauthorized();

            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()), //token claims Id
                new Claim(ClaimTypes.Name, userFromRepo.Username) //token claims username
            };

            // var key = new SymmetricSecurityKey(Encoding.UTF8
            // .GetBytes(_config.GetSection("AppSettings:Token").Value)); //MUST set TOKEN in appsettings.json

            // var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);

            // var tokenDescriptor = new SecurityTokenDescriptor
            // {
            //     Subject = new ClaimsIdentity(claims),
            //     Expires = DateTime.Now.AddDays(1),
            //     SigningCredentials = creds
            // };

            // var tokenHandler = new JwtSecurityTokenHandler(); //to make token

            // var token = tokenHandler.CreateToken(tokenDescriptor);

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

                var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("KeyForSignInSecret@1234"));  //this is token?
                var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);  

                var tokeOptions = new JwtSecurityToken(  
                    issuer: "http://localhost:5000",  
                    audience: "http://localhost:5000",  
                    claims: claims,  
                    expires: DateTime.Now.AddMinutes(30),  
                    signingCredentials: signinCredentials  
                );  

                var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);  
                return Ok(new { Token = tokenString });  
        }

    }
}

更新:检索数据仍然有问题,我尝试将令牌更改为JWT,但仍然无法获取数据。

enter image description here

这里是UsersController.cs,我不记得是怎么回事,但是在一行调试时,已经检索到数据。我评论了在GetUsers()函数上设置断点的行。我检索到它可以使用https在Visual Studio中运行。但是我又尝试了一次,但是没有用。我在没有https的Visual Studio代码上运行,我不知道如何将其更改为https。

UsersController.cs

using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using AutoMapper;
using DatingApp.API.Data;
using DatingApp.API.Dtos;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace DatingApp.API.Controllers
{
    [Authorize]
    [Route("api/[controller]")] //HttpGet a list of users
    [ApiController]
    public class UsersController : ControllerBase
    {
        private readonly IDatingRepository _repo;
        private readonly IMapper _mapper;
        public UsersController(IDatingRepository repo, IMapper mapper)
        {
            _mapper = mapper;
            _repo = repo;
        }

        [HttpGet]
        public async Task<IActionResult> GetUsers()
        {
            var users = await _repo.GetUsers();

            var usersToReturn = _mapper.Map<IEnumerable<UserForListDto>>(users); //Breakpoint: Users retrieved on debugging

            return Ok(usersToReturn);
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> GetUser(int id)
        {
            var user = await _repo.GetUser(id);

            var userToReturn = _mapper.Map<UserForDetailedDto>(user); //source

            return Ok(userToReturn);
        }

        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateUser(int id, UserForUpdateDto UserForUpdateDto)
        {
            if (id != int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value)) //Check if user is current user that passed token
            return Unauthorized();

            var userFromRepo = await _repo.GetUser(id);

            _mapper.Map(UserForUpdateDto, userFromRepo); 

            if (await _repo.SaveAll())
            return NoContent();

            throw new Exception($"Updating user {id} failed on save");
        }
    }
}

1 个答案:

答案 0 :(得分:0)

很抱歉延迟...

能否在URL中使用https而不是http 然后使用Authorization: JWT TOKEN_STRING 而不是Bearer ...