问题描述
感谢您对此的任何帮助。我目前正在从事一个项目,我们基本上必须将旧的 .Net Framework MVC 应用程序转换为 React 前端使用的 API。我们基本上可以在不使用 ApiController 的情况下将 MVC 控制器转换为 API 控制器。现在我们意识到我们需要保护 API,并决定实施 JWT。
我能够实现 JWT 令牌创建,并且我在返回 JWT 的帐户控制器中工作。我遇到的问题是,我想在某些端点上实现授权,但在现有控制器上运行时遇到了问题。 https://github.com/DavidParks8/Owin-Authorization/wiki/Claims-Based-Authorization 上的文档说明我应该能够在任一类型的控制器上使用授权,所以我不知道我做错了什么。
我想可能是因为我使用的是 Controller 而不是 ApiController,所以我设置了一个测试控制器并根据我遵循的 JWT 教程创建了一些基本端点。问题是,当我尝试测试这些端点时,它们根本没有被击中,而且我收到了 404。
这是我的配置:
{
string secretKey = WebConfigurationManager.AppSettings["SecretKey"];
SymmetricSecurityKey _signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
// Configure the db context,user manager and signin manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
//Enable JWT Authentication:
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationoptions
{
AuthenticationMode = AuthenticationMode.Active,TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,ValidateAudience = true,ValidateIssuerSigningKey = true,Validissuer = WebConfigurationManager.AppSettings["Audience"],ValidAudience = WebConfigurationManager.AppSettings["Audience"],IssuerSigningKey = _signingKey,ClockSkew = TimeSpan.Zero,ValidateLifetime = true,RequireExpirationTime = false
},});
//Authorizationoptions options = new Authorizationoptions();
app.UseAuthorization(options =>
{
options.AddPolicy("Principal",policy => policy.RequireClaim(Constants.JwtClaimIdentifiers.Rol,"Principal"));
options.AddPolicy("Employee",Constants.JwtClaims.Employee));
options.AddPolicy("Warranty",Constants.JwtClaims.Principal));
options.AddPolicy("Admin",Constants.JwtClaims.Principal));
});
这是基于我浏览过的文档和教程,并且正在使用 Microsoft.Owin.Security.Authorization 和 Microsoft.Owin.Security.Jwt
这是我的 WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
var json = config.Formatters.JsonFormatter;
json.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html"));
json.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
// Web API routes
config.MapHttpAttributeRoutes();
config.EnableCors();
//config.MessageHandlers.Add(new TokenValidationHandler());
config.Routes.MapHttpRoute(
name: "DefaultApi",routeTemplate: "api/{controller}/{action}/{id}",defaults: new { id = RouteParameter.Optional }
);
//var jsonpformatter = new JsonpMediaTypeFormatter(config.Formatters.JsonFormatter);
//config.Formatters.Insert(0,jsonpformatter);
}
}
这是我的测试控制器:
public class TestController : ApiController
{
[HttpGet]
[AllowAnonymous]
[Route("GetToken")]
public Object GetToken()
{
string key = "my_secret_key_12345"; //Secret key which will be used later during validation
var issuer = "example.com"; //normally this will be your site URL
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
var credentials = new SigningCredentials(securityKey,SecurityAlgorithms.HmacSha256);
//Create a List of Claims,Keep claims name short
var permClaims = new List<Claim>();
permClaims.Add(new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()));
permClaims.Add(new Claim("valid","1"));
permClaims.Add(new Claim("userid","1"));
permClaims.Add(new Claim("name","bilal"));
//Create Security Token object by giving required parameters
var token = new JwtSecurityToken(issuer,//Issuer
issuer,//Audience
permClaims,expires: DateTime.Now.AddDays(1),signingCredentials: credentials);
var jwtToken = new JwtSecurityTokenHandler().Writetoken(token);
return new { data = jwtToken };
}
[HttpGet]
[AllowAnonymous]
[Route("GetName1")]
public string GetName1()
{
if (User.Identity.IsAuthenticated)
{
var identity = User.Identity as ClaimsIdentity;
if (identity != null)
{
IEnumerable<Claim> claims = identity.Claims;
}
return "Valid";
}
else
{
return "Invalid";
}
}
[HttpPost]
[Route("GetName2")]
public Object GetName2()
{
if (User.Identity is ClaimsIdentity identity)
{
IEnumerable<Claim> claims = identity.Claims;
var name = claims.Where(p => p.Type == "name").FirstOrDefault()?.Value;
return new
{
data = name
};
}
return null;
}
}
所以当我尝试调用 http://localhost:29523/api/Test/GetToken 时,我收到了 404 错误。我正在使用 Postman,我可以访问另一个控制器中的端点,但它是一个 MVC 控制器,它不遵循 API 路由。例如,/registration/GetAccountManagementInfo?userGuid=a182235e-c71d-47a5-b31d-f556288b3c3f 有效,我能够得到响应。
总而言之,我用这个 ApiController 进行测试的原因是因为如果我能做到这一点,并获得授权在 ApiController 上工作,那么我将把我的“注册”控制器转换成一个 ApiController,因为我无法让该控制器使用我设置的授权中间件。
无论如何,我确定我可以提供其他信息,但此时我无能为力,试图找出如何进一步解决此问题。
我知道它正在尝试到达控制器,因为如果我添加一个构造函数,它会在构造函数处遇到断点,但无法从那里找到路由。我不知道我的设置有什么问题,但我觉得这个设置必须有一些电线在某个地方交叉。这是我继承的一个应用程序。我希望我能用 .Net 核心开始一个新项目,但我们现在没有时间。
无论如何,抱歉这篇文章的长度,我真的希望有人能给我一些指导。到目前为止,我已经浏览了无数其他帖子,但我还没有找到任何可以帮助我解决这个问题的帖子。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)