我正在开发一个应用程序,用户必须登录才能提交表单。我正在使用 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设置,但是也不起作用,我的控制器也只有[授权],但仍然是相同的错误。
我加了一个“?”在 userId 的 ComplaintForm 类中
public string? UserId { get; set; }
现在可以使用了:)