我正在创建一个使用JWT进行身份验证和授权的Core 2.0 Web API项目。我想要保护的控制器方法都使用Authorize
属性进行修饰。
这很有效。如果我在Bearer标题中传递JWT,我得到200.如果我没有通过JWT,我得到401.所有工作。在我的JWT中,我在授权时将用户ID存储在'UserId'字段中。
var claimsdata = new[] {
new Claim("UserId", user.Id.ToString()),
然后我有一个扩展方法:
public static string GetUserId(this IPrincipal user)
{
if (user == null)
return string.Empty;
var identity = (ClaimsIdentity)user.Identity;
IEnumerable<Claim> claims = identity.Claims;
return claims.FirstOrDefault(s => s.Type == "UserId")?.Value;
}
在我的控制器方法上,使用'Authorize',我经常需要用户的ID。所以我调用了我的GetUserId方法。这有效。但是,我不确定这是否是从令牌中获取Id的最佳方式。
int.TryParse(User.GetUserId(), out _userId);
我需要在所有控制器上使用该代码。我不能在构造函数中这样做,因为我认为这是错误的。
我在这里做对了吗?
答案 0 :(得分:9)
ControllerBase
包含User
ClaimsPrincipal
属性
您可以User.Claims
访问用户声明,无需IPrincipal
创建一个包含GetUserId
方法protected
public abstract class BaseController : Controller
{
protected int GetUserId()
{
return int.Parse(this.User.Claims.First(i => i.Type == "UserId").Value);
}
}
所有控制器都继承此形式,现在所有控制器都可以访问UserId
答案 1 :(得分:2)
还可以使用
扩展方法
像这样
var retrofitPart = module {
single<KakaoSearchService> {
Retrofit.Builder()
.baseUrl("https://dapi.kakao.com")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(KakaoSearchService::class.java)
}
}
var adapterPart = module {
factory {
MainSearchRecyclerViewAdapter()
}
}
var modelPart = module {
factory<DataModel> {
DataModelImpl(get())
}
}
var viewModelPart = module {
viewModel {
MainViewModel(get())
}
}
var myDiModule = listOf(retrofitPart, adapterPart, modelPart, viewModelPart)
并像这样在您的控制器中实现
public static long GetUserID(this ClaimsPrincipal User)
{
return long.Parse(User.Claims.First(i => i.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier").Value);
}
我希望它将对您有帮助
答案 2 :(得分:1)
首先,我通过注入IUserProvider
创建IHttpContextAccessor
接口,以在单元测试中为这些接口进行模拟。
public interface IUserProvider
{
string GetUserId();
}
比实现要
public class UserProvider : IUserProvider
{
private readonly IHttpContextAccessor _context;
public UserProvider (IHttpContextAccessor context)
{
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public string GetUserId()
{
return _context.HttpContext.User.Claims
.First(i => i.Type == ClaimTypes.NameIdentifier).Value;
}
}
因此,您可以在控制器中使用接口IUserProvider
,而无需继承
[Authorize]
[ApiController]
public class MyController : ControllerBase
{
private readonly IUserProvider _userProvider;
public MyController(IUserProvider userProvider)
{
_userProvider = userProvider ?? throw new ArgumentNullException(nameof(userProvider ));
}
[HttpGet]
[Route("api/My/Something")]
public async Task<ActionResult> GetSomething()
{
try
{
var userId= _userProvider.GetUserId();
}
}
}
答案 3 :(得分:-4)
var authenticatedUser = User.Identities.Select(c => c.Claims).ToArray()[0].ToArray()[0];
var userid = await userManager.FindByNameAsync(authenticatedUser['email']).Id;