1

Ich brauche zwei Authentifizierungstypen in ASP.NET Core 2.0 MVC-Anwendung zu unterstützen:Mehrere authenticaion Systeme in asp .net Kern 2.0

  1. AddIdentityServerAuthentication
  2. AddOpenIdConnect

Es war sehr einfach in ASP.NET Core 1.0 Version. Aber in Version 2.0 Version Syntax geändert. Das ist mein Code:

services.AddAuthentication(o => 
    { 
     o.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
     o.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; 
     o.DefaultAuthenticateScheme = OpenIdConnectDefaults.AuthenticationScheme; 
    }).AddIdentityServerAuthentication(options => 
    { 
     options.Authority = PlatformConfiguration.IdentityServerUri; 
     options.RequireHttpsMetadata = false; 
     options.SaveToken = true; 
     options.ApiSecret = "somesecret"; 
     options.ApiName = "some_api"; 
    }) 
    .AddCookie() 
    .AddOpenIdConnect(o => 
    { 
     o.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; 
     o.Authority = PlatformConfiguration.IdentityServerUri; 
     o.RequireHttpsMetadata = false; 
     o.ClientId = "some_viewer"; 
     o.UseTokenLifetime = true; 
     o.ResponseType = "id_token token"; 
     o.Scope.Add("openid"); 
     o.Scope.Add("roles"); 
     o.Scope.Add("profile"); 
     o.SaveTokens = true; 
     o.TokenValidationParameters = new TokenValidationParameters 
     { 
      NameClaimType = JwtClaimTypes.Name, 
      RoleClaimType = JwtClaimTypes.Role 
     }; 
    }); 

services.AddAuthorization(); 

Aber auf diese Weise funktioniert die Bearer-Authentifizierung nicht. Aufgrund der Standardschemas: DefaultChallengeScheme, DefaultAuthenticateScheme.
Wie definieren Sie mehrere Authentifizierungsschemata?

Antwort

2

Ich habe hinzugefügt Attribut

[Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme + "," + OpenIdConnectDefaults.AuthenticationScheme)] 

Und ich habe jetzt zwei Authentifizierungsschemata.

flexiblere Lösung diesen Code in Startup zu verwenden:

if (UseAuthorization) 
{ 
    var policy = new AuthorizationPolicyBuilder(IdentityServerAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme) 
     .RequireAuthenticatedUser() 
     .Build(); 

    options.Filters.Add(new AuthorizeFilter(policy)); 
} 
1

Hier ist ein Beispiel, das ich verwendet, um Webseiten mit JWT Token in ASP.NET 2.0

Sie die Syntax finden Ich kann zu authentifizieren verwendet, auch wenn es nicht alle Ihre Bedürfnisse enthält Ich hoffe, es wird Ihnen helfen.

Asp Net Kern

Erster Schritt ist die Methode schreiben, die Jwt Authentifizierung konfigurieren:

// Configure authentication with JWT (Json Web Token). 
public void ConfigureJwtAuthService(IServiceCollection services) 
{ 
    // Enable the use of an [Authorize(AuthenticationSchemes = 
    // JwtBearerDefaults.AuthenticationScheme)] 
    // attribute on methods and classes to protect. 
    services.AddAuthentication().AddJwtBearer(cfg => 
    { 
    cfg.RequireHttpsMetadata = false; 
    cfg.SaveToken = true; 
    cfg.TokenValidationParameters = new TokenValidationParameters() 
    { 
     IssuerSigningKey = JwtController.SecurityKey, 
     ValidAudience = JwtController.Audience, 
     ValidIssuer = JwtController.Issuer, 
     // When receiving a token, check that we've signed it. 
     ValidateIssuerSigningKey = true, 
     // When receiving a token, check that it is still valid. 
     ValidateLifetime = true, 
     // This defines the maximum allowable clock skew when validating 
     // the lifetime. As we're creating the tokens locally and validating 
     // them on the same machines which should have synchronised time, 
     // this can be set to zero. 
     ClockSkew = TimeSpan.FromMinutes(0) 
    }; 
    }); 
} 

Jetzt in den ConfigureServices() Methode des Startup.cs, können wir Rufen Sie ConfigureJwtAuthService() Methode zum Konfigurieren der JWT-Authentifizierung.

Dies ist die komplette Startup.cs:

using System; 
using Autofac; 
using ExpertCodeBlogWebApp.Controllers; 
using ExpertCodeBlogWebApp.Domain; 
using ExpertCodeBlogWebApp.Domain.Interfaces; 
using Microsoft.AspNetCore.Builder; 
using Microsoft.AspNetCore.Hosting; 
using Microsoft.AspNetCore.SpaServices.Webpack; 
using Microsoft.Extensions.Configuration; 
using Microsoft.Extensions.DependencyInjection; 

using Microsoft.IdentityModel.Tokens; 

namespace ExpertCodeBlogWebApp 
{ 
    public class Startup 
    { 
    public Startup(IConfiguration configuration) 
    { 
     Configuration = configuration; 
    } 

    public IConfiguration Configuration { get; } 

    // This method gets called by the runtime. Use this method to add 
    // services to the container. 
    public IServiceProvider ConfigureServices(IServiceCollection services) 
    { 
    services.AddMvc(); 

    // Configure jwt autenticazione 
    ConfigureJwtAuthService(services); 

    // Repositories 
    services.AddScoped<IUserRepository, UserRepository>(); 

    // Create the Autofac container builder for dependency injection 
    var builder = new ContainerBuilder(); 

    // Add any Autofac modules or registrations. 
    builder.RegisterModule(new AutofacModule()); 

    // Return ServiceProvider 
    var serviceProvider = services.BuildServiceProvider(); 
    return serviceProvider; 
    } 

    // Configure authentication with JWT (Json Web Token). 
    public void ConfigureJwtAuthService(IServiceCollection services) 
    { 
    // Enable the use of an [Authorize(AuthenticationSchemes = 
    // JwtBearerDefaults.AuthenticationScheme)] 
    // attribute on methods and classes to protect. 
    services.AddAuthentication().AddJwtBearer(cfg => 
    { 
     cfg.RequireHttpsMetadata = false; 
     cfg.SaveToken = true; 

     cfg.TokenValidationParameters = new TokenValidationParameters() 
     { 
     IssuerSigningKey = JwtController.SecurityKey, 
     ValidAudience = JwtController.Audience, 
     ValidIssuer = JwtController.Issuer, 
     // When receiving a token, check that we've signed it. 
     ValidateIssuerSigningKey = true, 
     // When receiving a token, check that it is still valid. 
     ValidateLifetime = true, 
     // This defines the maximum allowable clock skew when validating 
     // the lifetime. 
     // As we're creating the tokens locally and validating them on the 
     // same machines which should have synchronised time, this can be 
     // set to zero. 
     ClockSkew = TimeSpan.FromMinutes(0) 
     }; 
    }); 
    } 

    // This method gets called by the runtime. Use this method to configure 
    // the HTTP request pipeline. 
    public void Configure(IApplicationBuilder app, IHostingEnvironment env) 
    { 
    if (env.IsDevelopment()) 
    { 
     app.UseDeveloperExceptionPage(); 
     app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions 
     { 
     HotModuleReplacement = true 
     }); 
    } 
    else 
    { 
     app.UseExceptionHandler("/Home/Error"); 
    } 

    app.UseStaticFiles(); 

    app.UseMvc(routes => 
    { 
     routes.MapRoute(
     name: "default", 
     template: "{controller=Home}/{action=Index}/{id?}"); 

     routes.MapSpaFallbackRoute(
     name: "spa-fallback", 
     defaults: new { controller = "Home", action = "Index" }); 
     }); 
    } 
    } 

    // For dependency injection. 
    public class AutofacModule : Module 
    { 
    // Dependency Injection with Autofact 
    protected override void Load(ContainerBuilder builder) 
    { 
     builder.RegisterType<UserRepository>().As<IUserRepository>() 
     .SingleInstance(); 
    } 
    } 
} 

Die JwtController.cs

using System; 
using System.IdentityModel.Tokens.Jwt; 
using System.Security.Claims; 
using System.Security.Principal; 
using System.Text; 
using System.Threading.Tasks; 
using AutoMapper; 
using ExpertCodeBlogWebApp.Domain; 
using ExpertCodeBlogWebApp.Domain.Interfaces; 
using ExpertCodeBlogWebApp.Domain.Models; 
using ExpertCodeBlogWebApp.ViewModels; 
using Microsoft.AspNetCore.Mvc; 
using Microsoft.Extensions.Logging; 
using Microsoft.IdentityModel.Tokens; 
using Newtonsoft.Json; 

namespace ExpertCodeBlogWebApp.Controllers 
{ 

[Route("api/[controller]")] 
public class JwtController : Controller 
{ 
    #region Private Members 
    // JWT-related members 
    private TimeSpan TokenExpiration; 
    private SigningCredentials SigningCredentials; 
    // EF and Identity members, available through DI 
    private MyDbContext DbContext; 
    private IUserRepository _userRepository; 
    private readonly ILogger _logger; 
    #endregion Private Members 

    #region Static Members 
    private static readonly string PrivateKey = "my_PrivateKey"; 
    public static readonly SymmetricSecurityKey SecurityKey = 
    new SymmetricSecurityKey(Encoding.ASCII.GetBytes(PrivateKey)); 
    public static readonly string Issuer = "my_Issuer"; 
    public static readonly string Audience = "my_Audience"; 
    #endregion Static Members 

    #region Constructor 
    // I have used Autofac in the Startup.cs for dependency injection) 
    public JwtController(
    MyDbContext dbContext, 
    IUserRepository userRepository, 
    ILogger<JwtController> logger) 
    { 
    _logger = logger; 
    _userRepository = userRepository; 
    // Instantiate JWT-related members 
    TokenExpiration = TimeSpan.FromMinutes(10); 
    SigningCredentials = new SigningCredentials(SecurityKey, 
     SecurityAlgorithms.HmacSha256); 
    // Instantiate through Dependency Injection with Autofact 
    DbContext = dbContext; 
    } 
    #endregion Constructor 

    #region Public Methods 
    // Manages the request for a new authentication or the refresh of an 
    // already established one 
    [HttpPost("token")] 
    public async Task<IActionResult> 
    Authentication([FromBody]JwtRequestViewModel jwt) 
    { 
    if (ModelState.IsValid) 
    { 
     string grantType = jwt.GrantType; 
     if (grantType == "password") 
     { 
     string userName = jwt.UserName; 
     string password = jwt.Password; 

     // Password check required 
     var user = await 
      _userRepository.GetUserInfoWithCheckPwd(userName, password); 

     // Check if user is expired (check the ExpireDate property) 
     if (UserExpired(user)) 
      return BadRequest($"Account of {user.Name} expired!"); 

     if (UserEnabled(user)) 
      return await GenerateToken(user); 
     else 
      return BadRequest("User name or password invalid."); 
     } 
    } 
    else if (grantType == "refresh_token") 
    { 
     string userName = jwt.UserName; 

     // Refresh token (no password check required) 
     var user = await _userRepository.GetUserInfoByName(userName); 

     // Check if user is expired (check the ExpireDate property) 
     if (UserExpired(user)) 
     return BadRequest($"Account of {user.Name} expired!"); 

     string token = jwt.Token; 
     if (token == user.Token) 
     { 
     // Generate token and send it via a json-formatted string 
     return await GenerateToken(user); 
     } 
     else 
     { 
     return BadRequest("User token invalid."); 
     } 
    } 
    else 
     return BadRequest("Authentication type invalid."); 
    } 
    else 
    return BadRequest("Request invalid."); 
    } 
    #endregion Public Methods 

    #region Private Methods 
    private bool UserExpired(Users utente) 
    { 
    if (utente != null) 
     return utente.ExpireDate.CompareTo(DateTime.Now) < 0; 
    return true; 
    } 

    private bool UserEnabled(Users utente) 
    { 
    if (utente != null) 
     return utente.Enabled == true; 
    return false; 
    } 

    private JsonSerializerSettings DefaultJsonSettings 
    { 
    get 
    { 
     return new JsonSerializerSettings() 
     { 
     Formatting = Formatting.Indented 
     }; 
    } 
    } 

    private async Task<IActionResult> GenerateToken(Users user) 
    { 
    try 
    { 
     if (user != null) 
     { 
     var handler = new JwtSecurityTokenHandler(); 
     DateTime newTokenExpiration = DateTime.Now.Add(TokenExpiration); 

     ClaimsIdentity identity = new ClaimsIdentity(
      new GenericIdentity(user.Name, "TokenAuth"), 
      new[] { new Claim("ID", user.Id.ToString())} 
     ); 

     var securityToken = handler.CreateToken(new SecurityTokenDescriptor 
     { 
      Issuer = JwtController.Issuer, 
      Audience = JwtController.Audience, 
      SigningCredentials = SigningCredentials, 
      Subject = identity, 
      Expires = newTokenExpiration 
     }); 
     string encodedToken = handler.WriteToken(securityToken); 

     // Update token data on database 
     await _userRepository.UpdateTokenData(user.Name, encodedToken, 
      newTokenExpiration); 
     // Build the json response 
     // (I use Automapper to maps an object into another object) 
     var jwtResponse = Mapper.Map<JwtResponseViewModel>(user); 
     jwtResponse.AccessToken = encodedToken; 
     jwtResponse.Expiration = (int)TokenExpiration.TotalSeconds; 
     return Ok(jwtResponse); 
     } 
     return NotFound(); 
     } 
     catch(Exception e) 
     { 
     return BadRequest(e.Message); 
     } 
    } 
    #endregion 
    } 
} 

Auf meinem Projekt, das ich Angular verwenden.Für Aufruf JwtController Methode Eckig:

login(userName: string, password: string) 
{ 
    return this.getLoginEndpoint(userName, password) 
    .map((response: Response) => this.processLoginResponse(response)); 
} 

getLoginEndpoint(userName: string, password: string): Observable<Response> 
{ 
    // Body 
    // JwtRequest is a model class that I use to send info to the controller 
    let jwt = new JwtRequest(); 
    jwt.GrantType = "password"; 
    jwt.UserName = userName; 
    jwt.Password = password; 
    jwt.ClientId = "my_Issuer"; 
    // Post requiest (I use getAuthHeader that attach to the header the 
    // authentication token, but it can also be omitted because it is ignored 
    // by the JwtController 
    return this.http.post(this.loginUrl, JSON.stringify(jwt), 
    this.getAuthHeader(true)) 
} 

protected getAuthHeader(includeJsonContentType?: boolean): RequestOptions 
{ 
    // Hera I use this.authService.accessToken that is a my service where 
    // I have store the token received from the server 
    let headers = new Headers({ 
    'Authorization': 'Bearer ' + this.authService.accessToken }); 

    if (includeJsonContentType) 
    headers.append("Content-Type", "application/json"); 

    headers.append("Accept", `application/vnd.iman.v01+json, 
    application/json, text/plain, */*`); 
    headers.append("App-Version", "01"); 

    return new RequestOptions({ headers: headers }); 
} 

private processLoginResponse(response: Response) 
{ 
    // process the response.. 
} 

Auf den Controllern Klassen (oder Methoden), die Sie nur von authentifizierten Benutzern zugänglich sein wollen (nicht auf Ihrem JwtController weil seine Methode von allen Benutzern zugänglich sein müssen) können Sie einstellen, :

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] 

die Controller-Methode von Angular aufrufen, die eine Authentifizierung erfordern, müssen Sie den Token in den Header mit dem getAuthHeader() Methode befestigen.

Ich hoffe, dieser Beitrag kann Ihnen helfen.

+0

Das ist viel besser, danke. –

Verwandte Themen