API端的用户授权与.net核心

时间:2018-04-17 07:11:36

标签: c# asp.net-core .net-core authorization asp.net-core-webapi

我在.net核心中编写了一个使用API​​和网站的网络应用程序。

Web服务构建JWT令牌。 这是服务配置(删除不必要的部分)

foo

到目前为止,这么好。登录有效,我的网站端授权有效,我可以使用foo属性。

问题是,我已登录网站,但未登录API。

我不能将public void ConfigureServices(IServiceCollection services) { //... var tokenValidationParameters = new TokenValidationParameters { // The signing key must match! ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, // Validate the JWT Issuer (iss) claim ValidateIssuer = true, ValidIssuer = "ExampleIssuer", // Validate the JWT Audience (aud) claim ValidateAudience = true, ValidAudience = "ExampleAudience", // Validate the token expiry ValidateLifetime = true, // If you want to allow a certain amount of clock drift, set that here: ClockSkew = TimeSpan.Zero, }; var serialiser = services.BuildServiceProvider().GetService<IDataSerializer<AuthenticationTicket>>(); var dataProtector = services.BuildServiceProvider().GetDataProtector(new string[] {$"IronSphere.Web.Site-Auth"}); services .AddAuthentication(o => { o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(cfg => { cfg.RequireHttpsMetadata = false; cfg.SaveToken = true; cfg.TokenValidationParameters = tokenValidationParameters; }) .AddCookie(cookie => { cookie.Cookie.Name = "access_token"; cookie.TicketDataFormat = new JwtTokenValidator( SecurityAlgorithms.HmacSha256, tokenValidationParameters, serialiser, dataProtector); }); //... } - 属性用于我的API方法(是的,当然,这是有意义的。)

因此,当我登录时,每次调用API时,我也会在标头中发送令牌(这样,我可以在API控制器中读取它)。我想我需要反序列化它。

我尝试使用依赖注入将[Authorize]放入我的控制器中:

[Authorize]

然后从标题中取出密钥,反序列化,并且我的用户对象包含声明。但是,当我尝试注入任何控制器时,它会使我的应用程序崩溃(只是一条消息,即dotnet停止工作)

任何想法如何在api被调用时验证用户? (如果你需要,我可以发布更多代码,只是不想填写太多代码)

1 个答案:

答案 0 :(得分:1)

所以@Tseng在输入后给了我很多帮助,这是我的结果(关于如何做得更好的更多输入会很好):

  1. 在添加Startup.cs

    时添加了令牌的非保护器作为服务
    services.AddTransient<IJwtTokenService, JwtTokenService>();
    
  2. IJwtTokenService

    public interface IJwtTokenService
    {
        string UnprotectToken(string protectedText);
    }
    
  3. 已实施的JwtTokenService

    public class JwtTokenService:IJwtTokenService
    {
        private readonly IDataSerializer<AuthenticationTicket> _ticketSerializer;
        private readonly IDataProtector _dataProtector;
    
        public JwtTokenService(IDataSerializer<AuthenticationTicket> serializer, IDataProtector protector)
        {
            _ticketSerializer = serializer;
            _dataProtector = protector;
        }
    
        public string UnprotectToken(string protectedText)
        {
            SecurityKey signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(" ......... "));
    
            TokenValidationParameters tokenValidationParameters =
                _getTokenValidationParameters();
    
            JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
            AuthenticationTicket authTicket;
            string embeddedJwt;
    
            try
            {
                // logic to deserialize token
                // logic to validate token
                // more logic... (algorithm,..)
            }
            catch (Exception)
            {
                return null;
            }
    
            return embeddedJwt;
        }
    }
    
  4. 所以在服务中我还必须添加IDataProtector。之前它抛出了一个例外。

    services.AddTransient(x => x.GetDataProtector(new[] {$"auth"}));
    
  5. 然后我可以将IJwtTokenService添加到构造函数中以进行依赖注入,取消保护它并使用标头发送它:

    protected ServiceBase(
        IHttpContextAccessor contextAccessor, 
        IJwtTokenService jwtTokenService, 
        IMemoryCache memoryCache = null)
    {
        MemoryCache = memoryCache ?? new MemoryCache(new MemoryCacheOptions());
        CachingFunctionalty = new CachingFunctionality();
        HttpContextAccessor = contextAccessor;
        JwtTokenService = jwtTokenService;
    }
    
    protected RestClient CreateClient()
    {
        RestClient restClient = new RestClient(ServiceAdress);
    
        var token = HttpContextAccessor.HttpContext.Request.Cookies["access_token"];
    
        if (string.IsNullOrWhiteSpace(token)) return restClient;
    
        var unprotected = JwtTokenService.UnprotectToken(token);
        restClient.AuthenticationHeaderValue = new AuthenticationHeaderValue("Bearer", unprotected);
    
        return restClient;
    }
    
  6. 现在我的API与AuthorizeAttribute

    一起使用