【发布时间】:2021-12-25 23:13:50
【问题描述】:
我正在使用 Asp net core Web Api 构建 React 应用程序。我实现了 JWT 授权,我将 jwt 令牌存储在本地存储中。我是否需要将其与授权标头“Bearer”的每个请求一起发送到我的 webapi?我是否需要每次在后端检查标头中的令牌?我希望我的用户在提出请求时获得授权,但我不知道该怎么做。
这是我的 JwtService
public class JWTAuthService
{
private readonly JwtTokenConfig jwtTokenConfig;
private readonly ILogger<JWTAuthService> logger;
public JWTAuthService(
JwtTokenConfig jwtTokenConfig,
ILogger<JWTAuthService> logger)
{
this.jwtTokenConfig = jwtTokenConfig;
this.logger = logger;
}
public string BuildToken(Claim[] claims)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.jwtTokenConfig.Secret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: this.jwtTokenConfig.Issuer,
audience: this.jwtTokenConfig.Audience,
notBefore: DateTime.Now,
claims: claims,
expires: DateTime.Now.AddMinutes(this.jwtTokenConfig.AccessTokenExpiration),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
public string BuildRefreshToken()
{
var randomNumber = new byte[32];
using var randomNumberGenerator = RandomNumberGenerator.Create();
randomNumberGenerator.GetBytes(randomNumber);
return Convert.ToBase64String(randomNumber);
}
public ClaimsPrincipal GetPrincipalFromToken(string token)
{
JwtSecurityTokenHandler tokenValidator = new();
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.jwtTokenConfig.Secret));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var parameters = new TokenValidationParameters
{
ValidateAudience = false,
ValidateIssuer = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateLifetime = false,
};
try
{
var principal = tokenValidator.ValidateToken(token, parameters, out var securityToken);
if (!(securityToken is JwtSecurityToken jwtSecurityToken) || !jwtSecurityToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase))
{
this.logger.LogError($"Token validation failed");
return null;
}
return principal;
}
catch (Exception e)
{
this.logger.LogError($"Token validation failed: {e.Message}");
return null;
}
}
}
}
这是我返回用户 ID 的身份验证
[HttpPost("user")]
public string UserAuth([FromBody] string accessToken)
{
ClaimsPrincipal claimsPrincipal = this.jwtAuthService.GetPrincipalFromToken(accessToken);
string id = claimsPrincipal.Claims.First(c => c.Type == "id").Value;
var userId = JsonConvert.SerializeObject(id);
return userId;
}
这是我在 react 中的登录组件
const Login = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [redirect, setRedirect] = useState(false);
const submit = async (e) => {
e.preventDefault();
const user = {
username,
password,
};
await fetch('https://localhost:44366/api/AppUsers/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(user),
}).then(response => response.json()).then(res => {
if (res.AccessToken) {
localStorage.setItem("jwt", res.AccessToken);
}
})
setRedirect(true);
}
if (redirect) {
return <Redirect to="/" />
}
here is return state
我的主页上有帖子,用户可以在其中提交 cmets。我需要 userId 向我的 Api 发出发布请求。首先,我请求获取 userId,然后发布评论。我知道这不是办法,我需要一些帮助来了解如何做到这一点。
const Card = (props) => {
const [text, setText] = useState("");
const [showMore, setShowMore] = useState(false);
const [userId, setUserId] = useState();
const {
postId,
key,
profilePicture,
image,
comments,
likedByText,
likedByNumber,
hours,
content,
title,
accountName,
} = props;
const submitComment = (e, postId) => {
e.preventDefault();
const jwt = localStorage.getItem("jwt");
const fetchUrl = `https://localhost:44366/api/AppUsers/user`;
const fetchData = () => {
fetch((fetchUrl),
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(jwt),
})
.then((res) => res.json())
.then((result) => setUserId(result))
.catch((err) => {
console.log(err);
});
};
fetchData();
const id = postId;
const data = {
Content: text,
UserId: userId,
PostId: id ,
}
fetch('https://localhost:44366/api/Comments/create', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
.catch((error) => {
console.error('Error:', error);
});
setText('');
}
return (
<div className="card" key={id}>
<header>
<Profile iconSize="big" image={profilePicture} accountName={accountName} />
</header>
<p className='text-center'>{title}</p>
<p className='text-center'> {content}</p>
<ImageSlider slides={image} />
<CardMenu />
<div className="likedBy">
<Profile iconSize="small" image={profilePicture} />
<span>
Liked by <strong>{likedByText}</strong> and{" "}
<strong>{comments.Lenght} 50 others</strong>
</span>
</div>
<div className="comments">
{comments?.slice(0, 5).map((comment) => (
<Comment
key={comment.id}
accountName={comment.User.FirstName ? comment.User.FirstName : null}
comment={comment.Content}
/>
)
)}
{showMore && comments?.slice(5).map((comment) => (
<Comment
key={comment.id}
accountName={comment.User.FirstName ? comment.User.FirstName : null}
comment={comment.Content}
/>
))}
<button type="button" className="button" onClick={() => setShowMore(true)}>Show more comments</button>
</div>
<div className="timePosted">Before {hours} hours.</div>
<form data={postId} onSubmit={e => submitComment(e, id)}>
<div className="addComment">
<textarea type="text" value={text} placeholder="Напишете коментар" className="commentText" onChange={(e) => setText(e.target.value)} />
<button className="btn btn-primary" type="submit" >Post</button>
</div>
</form>
</div>
);
}
export default Card;
【问题讨论】:
标签: c# reactjs .net asp.net-core react-hooks