gpt4 book ai didi

identityserver3 - asp .net core 2.0中的多种身份验证方案

转载 作者:行者123 更新时间:2023-12-02 20:37:49 30 4
gpt4 key购买 nike

我需要在 ASP.NET Core 2.0 MVC 应用程序中支持两种身份验证类型:

  1. 添加身份服务器身份验证
  2. 添加OpenIdConnect

ASP.NET Core 1.0版本中这非常容易。但在 2.0 版本中语法发生了变化。这是我的代码:

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();

但是这样,Bearer认证就不起作用了。由于默认方案:DefaultChallengeSchemeDefaultAuthenticateScheme
如何定义多种认证方案?

最佳答案

这是我在 ASP.NET 2.0 中使用 JWT token 对网页进行身份验证的示例

您可以找到我使用的语法,即使它没有包含您的所有需求,我希望它会对您有所帮助。

Asp Net Core

第一步是编写配置 Jwt 身份验证的方法:

// 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)
};
});
}

现在,在 Startup.csConfigureServices() 方法中,我们可以调用 ConfigureJwtAuthService() 方法来配置 Jwt 身份验证。

这是完整的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();
}
}
}

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
}
}

在我的项目中我使用 Angular。通过 Angular 调用 JwtController 方法:

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..
}

在您希望仅由经过身份验证的用户访问的 Controller 类(或方法)上(不是在您的 JwtController 上,因为它的方法必须由所有用户访问),您可以设置:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

要从 Angular 调用需要身份验证的 Controller 方法,您需要使用 getAuthHeader() 方法将 token 附加到 header 中。

希望这篇文章可以帮助到您。

关于identityserver3 - asp .net core 2.0中的多种身份验证方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46691485/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com