尝试访问授权控制器时需要UserId

问题描述 投票:0回答:1

我正在开发一个应用程序,用户必须登录才能提交表单。我正在使用 jwt 并将它们存储在会话中,我也在本地尝试过。当我登录时,我可以在控制台中看到令牌,在进入我的“提交表单”网站后,我检查令牌仍然存在。问题是,在我提交后,我收到错误 400,“需要 userId”,我不知道为什么会收到此错误,因为当我签入控制台时,我可以看到该表单使用与登录令牌相同的令牌。

这是我的一些用户控制器代码:

      public UserController(HelpDeskDbContext context, UserManager<User> userManager, SignInManager<User> signInManager, IConfiguration configuration)
  {
    _context = context;
    _userManager = userManager;
    _signInManager = signInManager;
    _jwtKey = configuration["Jwt:Key"];
  }[Authorize(AuthenticationSchemes = "Bearer")]
[HttpPost("createComplaint")]
public async Task<IActionResult> CreateComplaint([FromBody] ComplaintForm complaintForm)
{
  var userId = _userManager.GetUserId(User);
  complaintForm.UserId = userId;
  _context.ComplaintForms.Add(complaintForm);
  await _context.SaveChangesAsync();
  return Ok(complaintForm);
}

[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginViewModel model)
{
  if (ModelState.IsValid)
  {
    var user = await _userManager.FindByEmailAsync(model.Email);
    if (user != null)
    {
      var passwordValid = await _userManager.CheckPasswordAsync(user, model.Password);
      if (passwordValid)
      {
        var token = GenerateJwtToken(user);
        return Ok(new { token, Role = user.Role });
      }
    }
    return Unauthorized("Invalid login attempt.");
  }
  return BadRequest("Invalid login attempt.");
}  private string GenerateJwtToken(User user)
  {
    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.UTF8.GetBytes(_jwtKey);
    var tokenDescriptor = new SecurityTokenDescriptor
    {
      Subject = new ClaimsIdentity(new[]
        {
              new Claim(ClaimTypes.NameIdentifier, user.Id),
              new Claim(ClaimTypes.Name, user.UserName), // Optionally add more claims
          }),
      Expires = DateTime.UtcNow.AddDays(7),
      SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
      Issuer = "YourIssuer", // Ensure these match in your token validation settings
      Audience = "YourAudience"
    };
    var token = tokenHandler.CreateToken(tokenDescriptor);
    return tokenHandler.WriteToken(token);
  }  public class RegisterViewModel
  {
    public string? Email { get; set; }
    public string? Password { get; set; }
  }

  public class LoginViewModel
  {
    public string? Email { get; set; }
    public string? Password { get; set; }
    public bool RememberMe { get; set; }
  }

我的投诉表类别和用户类别:

public class ComplaintForm
 {
   public int Id { get; set; }
   public string? Subject { get; set; }
   public string? Description { get; set; }
   public string? FilePath { get; set; }
   public FormStatus Status { get; set; }
   public string UserId { get; set; }
   public string? AssignedWorkerId { get; set; }
   public DateTime DueDate { get; set; }

   [JsonIgnore]
   public virtual User? User { get; set; }
   [JsonIgnore]
   public virtual User? AssignedWorker { get; set; }
   [JsonIgnore]
   public virtual ICollection<Comment>? Comments { get; set; }
 }  public class User : IdentityUser
  {

    public string? Role { get; set; }
    public virtual ICollection<ComplaintForm>? ComplaintForms { get; set; }

    public virtual ICollection<ComplaintForm>? AssignedComplaintForms { get; set; }
  }

我的appsettings.json:

"Jwt": {
   "Key": "my key",
   "Issuer": "YourIssuer",
   "Audience": "YourAudience"
 },

我的程序.cs:

var jwtSettings = builder.Configuration.GetSection("Jwt");
var key = Encoding.UTF8.GetBytes(jwtSettings["Key"]);

builder.Services.AddAuthentication(options =>
{
  options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
  options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
  options.RequireHttpsMetadata = false;
  options.SaveToken = true;
  options.TokenValidationParameters = new TokenValidationParameters
  {
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(key),
    ValidateIssuer = false,
    ValidateAudience = false,
    ValidIssuer = jwtSettings["Issuer"],
    ValidAudience = jwtSettings["Audience"]
  };
});

// Add services to the container.
builder.Services.AddControllers();

// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();


builder.Services.AddDbContext<mydbcontext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("mydbcontext")));

builder.Services.AddIdentity<User, IdentityRole>()
    .AddEntityFrameworkStores<HelpDeskDbContext>()
    .AddDefaultTokenProviders();



builder.Services.AddControllers().AddJsonOptions(options =>
{
  options.JsonSerializerOptions.MaxDepth = 64;

});

builder.Services.AddCors(options =>
{
  options.AddPolicy("AllowSpecificOrigin", builder =>
  {
    builder.WithOrigins("http://localhost:mylocalhost")
           .AllowAnyMethod()
           .AllowAnyHeader()
           .AllowCredentials();
  });
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
  app.UseSwagger();
  app.UseSwaggerUI();
}

app.UseHttpsRedirection();

// Apply the CORS policy
app.UseCors("AllowSpecificOrigin");

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

我的前端正在反应,我有以下文件:

我的 api.js:

export const api = axios.create({
  baseURL: API_BASE_URL,
  headers: {
    'Content-Type': 'application/json'
  },
});

api.interceptors.request.use((config) => {
  const token = sessionStorage.getItem('authToken');
  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`;
  }
  return config;
}, (error) => {
  return Promise.reject(error);
});


// Authentication
export const register = (data) => api.post('/user/register', data);

export const login = async (data) => {
  try {
    const response = await api.post('/user/login', data);
    return {
        token: response.data.token, // Ensure this matches your API response structure
        role: response.data.role,   // Ensure this matches your API response structure
      };
  } catch (error) {
    console.error('Login failed', error);
    throw error;
  }
};

// User Complaints
export const createComplaint = (data) => api.post('/user/createComplaint', data);

export const getUserComplaints = async () => {
  try {
    const response = await api.get('/user/complaints');
    return response.data;
  } catch (error) {
    console.error('Failed to get user complaints', error);
    throw error;
  }
};

这是我的 auth.js、login.js 和 form.js(我在其中提交表单)

export const isAuthenticated = () => {
  const token = sessionStorage.getItem('authToken');
  return token !== null;
};
import React, { useState } from 'react';
import { login } from '../api'; // Adjust the import path as needed
import { useNavigate } from 'react-router-dom';

function Login() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const navigate = useNavigate(); // Initialize useNavigate hook

  const handleLogin = async (e) => {
    e.preventDefault();
    try {
      const { token, role } = await login({ email, password });
      console.log('Login successful:', token);

      // Store the token in sessionStorage
      sessionStorage.setItem('authToken', token);

      // Redirect based on the role
      if (role === 'Admin') {
        navigate('/admin');
      } else if (role === 'Worker') {
        navigate('/worker'); // Redirect to worker dashboard
      } else {
        navigate('/'); // Redirect to the homepage or user dashboard
      }
    } catch (err) {
      setError('Login failed. Please check your credentials and try again.');
    }
  };

  return (
    <div>
      <h2>Login</h2>
      <form onSubmit={handleLogin}>
        <div>
          <label>Email:</label>
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            required
          />
        </div>
        <div>
          <label>Password:</label>
          <input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            required
          />
        </div>
        <button type="submit">Login</button>
      </form>
      {error && <p>{error}</p>}
    </div>
  );
}

export default Login;
import React, { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { createComplaint } from '../api'; 

const ComplaintForm = () => {
  const [subject, setSubject] = useState('');
  const [description, setDescription] = useState('');
  const [filePath, setFilePath] = useState('');
  const navigate = useNavigate();

  const handleSubmit = async (e) => {
    e.preventDefault();
  
    const data = {
      subject,
      description,
      filePath
    };
  
    try {
      await createComplaint(data);
      navigate('/success'); 
    } catch (error) {
      console.error('Error submitting complaint', error);
      
      if (error.response && error.response.data) {
        console.error('Error response:', error.response.data);
      } else {
        console.error('Error message:', error.message);
      }
      alert('Failed to submit complaint');
    }
  };
  

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>Subject</label>
        <input
          type="text"
          value={subject}
          onChange={(e) => setSubject(e.target.value)}
          required
        />
      </div>
      <div>
        <label>Description</label>
        <textarea
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          required
        ></textarea>
      </div>
      <div>
        <label>File Path</label>
        <input
          type="text"
          value={filePath}
          onChange={(e) => setFilePath(e.target.value)}
        />
      </div>
      <button type="submit">Submit Complaint</button>
    </form>
  );
};

export default ComplaintForm;

老实说,任何帮助将不胜感激,因为我已经被困在这个问题上很长一段时间了,我在互联网上查找了其他解决方案,但我找不到任何对我的情况有帮助的解决方案,我尝试将identityuser放入program.cs中,然后再进行身份验证jwt设置,但是也不起作用,我的控制器也只有[授权],但仍然是相同的错误。

reactjs .net api authentication
1个回答
0
投票

我加了一个“?”在 userId 的 ComplaintForm 类中

public string? UserId { get; set; }

现在可以使用了:)

© www.soinside.com 2019 - 2024. All rights reserved.