ASP.NET 코어 웹 API 인증
웹 서비스에서 인증을 설정하는 방법에 대해 고민하고 있습니다.이 서비스는 ASP.NET Core 웹 API를 사용하여 빌드됩니다.
모든 클라이언트(WPF 응용 프로그램)는 동일한 자격 증명을 사용하여 웹 서비스 작업을 호출해야 합니다.
조사한 결과, HTTP 요청 헤더에 사용자 이름과 비밀번호를 보내는 기본 인증을 생각해냈습니다.하지만 몇 시간 동안 조사한 결과, ASP.NET Core에서는 기본 인증 방식이 아닌 것 같습니다.
제가 찾은 대부분의 리소스는 OAuth 또는 일부 다른 미들웨어를 사용하여 인증을 구현하는 것입니다.그러나 이는 ASP.NET Core의 Identity 부분을 사용하는 것뿐만 아니라 제 시나리오에 비해 너무 큰 것 같습니다.
그렇다면 ASP.NET Core 웹 서비스에서 사용자 이름과 암호를 사용한 간단한 인증이라는 목표를 달성하는 올바른 방법은 무엇일까요?
제가 올바른 방향을 제시한 후에 저의 완벽한 해결책은 다음과 같습니다.
들어오는 모든 요청에 대해 실행되고 요청에 올바른 자격 증명이 있는지 확인하는 미들웨어 클래스입니다.자격 증명이 없거나 잘못된 경우 서비스는 즉시 401 무단 오류로 응답합니다.
public class AuthenticationMiddleware
{
private readonly RequestDelegate _next;
public AuthenticationMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
string authHeader = context.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic"))
{
//Extract credentials
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
int seperatorIndex = usernamePassword.IndexOf(':');
var username = usernamePassword.Substring(0, seperatorIndex);
var password = usernamePassword.Substring(seperatorIndex + 1);
if(username == "test" && password == "test" )
{
await _next.Invoke(context);
}
else
{
context.Response.StatusCode = 401; //Unauthorized
return;
}
}
else
{
// no authorization header
context.Response.StatusCode = 401; //Unauthorized
return;
}
}
}
서비스 시작 클래스의 구성 메서드에서 미들웨어 확장을 호출해야 합니다.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseMiddleware<AuthenticationMiddleware>();
app.UseMvc();
}
그리고 그게 전부야! :)
의 미들웨어에 매우 적합한 리소스입니다.NetCore 및 인증은 https://www.exceptionnotfound.net/writing-custom-middleware-in-asp-net-core-1-0/ 에서 확인할 수 있습니다.
기본 인증을 처리하는 미들웨어를 구현할 수 있습니다.
public async Task Invoke(HttpContext context)
{
var authHeader = context.Request.Headers.Get("Authorization");
if (authHeader != null && authHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
{
var token = authHeader.Substring("Basic ".Length).Trim();
System.Console.WriteLine(token);
var credentialstring = Encoding.UTF8.GetString(Convert.FromBase64String(token));
var credentials = credentialstring.Split(':');
if(credentials[0] == "admin" && credentials[1] == "admin")
{
var claims = new[] { new Claim("name", credentials[0]), new Claim(ClaimTypes.Role, "Admin") };
var identity = new ClaimsIdentity(claims, "Basic");
context.User = new ClaimsPrincipal(identity);
}
}
else
{
context.Response.StatusCode = 401;
context.Response.Headers.Set("WWW-Authenticate", "Basic realm=\"dotnetthoughts.net\"");
}
await _next(context);
}
이 코드는 asp.net 코어의 베타 버전으로 작성되었습니다.도움이 되길 바랍니다.
예를 들어 특정 컨트롤러에만 이 기능을 사용하려면 다음을 사용합니다.
app.UseWhen(x => (x.Request.Path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase)),
builder =>
{
builder.UseMiddleware<AuthenticationMiddleware>();
});
JWT(Json Web Tokens)로 가시면 될 것 같습니다.
먼저 패키지 시스템을 설치해야 합니다.아이덴티티 모델.토큰.Jwt:
$ dotnet add package System.IdentityModel.Tokens.Jwt
다음과 같은 토큰 생성 및 인증을 위한 컨트롤러를 추가해야 합니다.
public class TokenController : Controller
{
[Route("/token")]
[HttpPost]
public IActionResult Create(string username, string password)
{
if (IsValidUserAndPasswordCombination(username, password))
return new ObjectResult(GenerateToken(username));
return BadRequest();
}
private bool IsValidUserAndPasswordCombination(string username, string password)
{
return !string.IsNullOrEmpty(username) && username == password;
}
private string GenerateToken(string username)
{
var claims = new Claim[]
{
new Claim(ClaimTypes.Name, username),
new Claim(JwtRegisteredClaimNames.Nbf, new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
new Claim(JwtRegisteredClaimNames.Exp, new DateTimeOffset(DateTime.Now.AddDays(1)).ToUnixTimeSeconds().ToString()),
};
var token = new JwtSecurityToken(
new JwtHeader(new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Secret Key You Devise")),
SecurityAlgorithms.HmacSha256)),
new JwtPayload(claims));
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
Startup.cs 클래스를 다음과 같이 업데이트합니다.
namespace WebAPISecurity
{
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 void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = "JwtBearer";
options.DefaultChallengeScheme = "JwtBearer";
})
.AddJwtBearer("JwtBearer", jwtBearerOptions =>
{
jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Secret Key You Devise")),
ValidateIssuer = false,
//ValidIssuer = "The name of the issuer",
ValidateAudience = false,
//ValidAudience = "The name of the audience",
ValidateLifetime = true, //validate the expiration and not before values in the token
ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date
};
});
}
// 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.UseAuthentication();
app.UseMvc();
}
}
그리고 그게 다야, 이제 남은 것은.[Authorize]
원하는 컨트롤러 또는 작업의 속성을 지정할 수 있습니다.
다음은 완전한 직선 자습서 링크입니다.
http://www.blinkingcaret.com/2017/09/06/secure-web-api-in-asp-net-core/
는 구습니다를 했습니다.BasicAuthenticationHandler
할 수 기본 할 수 있습니다.Authorize
그리고.AllowAnonymous
.
public class BasicAuthenticationHandler : AuthenticationHandler<BasicAuthenticationOptions>
{
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
var authHeader = (string)this.Request.Headers["Authorization"];
if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
{
//Extract credentials
string encodedUsernamePassword = authHeader.Substring("Basic ".Length).Trim();
Encoding encoding = Encoding.GetEncoding("iso-8859-1");
string usernamePassword = encoding.GetString(Convert.FromBase64String(encodedUsernamePassword));
int seperatorIndex = usernamePassword.IndexOf(':', StringComparison.OrdinalIgnoreCase);
var username = usernamePassword.Substring(0, seperatorIndex);
var password = usernamePassword.Substring(seperatorIndex + 1);
//you also can use this.Context.Authentication here
if (username == "test" && password == "test")
{
var user = new GenericPrincipal(new GenericIdentity("User"), null);
var ticket = new AuthenticationTicket(user, new AuthenticationProperties(), Options.AuthenticationScheme);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
else
{
return Task.FromResult(AuthenticateResult.Fail("No valid user."));
}
}
this.Response.Headers["WWW-Authenticate"]= "Basic realm=\"yourawesomesite.net\"";
return Task.FromResult(AuthenticateResult.Fail("No credentials."));
}
}
public class BasicAuthenticationMiddleware : AuthenticationMiddleware<BasicAuthenticationOptions>
{
public BasicAuthenticationMiddleware(
RequestDelegate next,
IOptions<BasicAuthenticationOptions> options,
ILoggerFactory loggerFactory,
UrlEncoder encoder)
: base(next, options, loggerFactory, encoder)
{
}
protected override AuthenticationHandler<BasicAuthenticationOptions> CreateHandler()
{
return new BasicAuthenticationHandler();
}
}
public class BasicAuthenticationOptions : AuthenticationOptions
{
public BasicAuthenticationOptions()
{
AuthenticationScheme = "Basic";
AutomaticAuthenticate = true;
}
}
.cs에서 등록 - Startup.cs 에서 -app.UseMiddleware<BasicAuthenticationMiddleware>();
Autorize " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
[Authorize(ActiveAuthenticationSchemes = "Basic")]
[Route("api/[controller]")]
public class ValuesController : Controller
" 성속사니다합용및다"를 합니다.AllowAnonymous
응용 프로그램 수준에서 인증 필터를 적용하는 경우.
사용할 수 있습니다.ActionFilterAttribute
public class BasicAuthAttribute : ActionFilterAttribute
{
public string BasicRealm { get; set; }
protected NetworkCredential Nc { get; set; }
public BasicAuthAttribute(string user,string pass)
{
this.Nc = new NetworkCredential(user,pass);
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var req = filterContext.HttpContext.Request;
var auth = req.Headers["Authorization"].ToString();
if (!String.IsNullOrEmpty(auth))
{
var cred = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(auth.Substring(6)))
.Split(':');
var user = new {Name = cred[0], Pass = cred[1]};
if (user.Name == Nc.UserName && user.Pass == Nc.Password) return;
}
filterContext.HttpContext.Response.Headers.Add("WWW-Authenticate",
String.Format("Basic realm=\"{0}\"", BasicRealm ?? "Ryadel"));
filterContext.Result = new UnauthorizedResult();
}
}
컨트롤러에 속성을 추가합니다.
[BasicAuth("USR", "MyPassword")]
이전 게시물에서 올바르게 언급했듯이, 한 가지 방법은 사용자 지정 기본 인증 미들웨어를 구현하는 것입니다.나는 이 블로그에서 설명과 함께 최고의 작동 코드를 찾았습니다: 맞춤형 미들웨어를 사용한 기본 인증.
저는 같은 블로그를 참조했지만 두 번의 각색 작업을 해야 했습니다.
- 스타트업 파일에 미들웨어 추가 -> 기능 구성 시 앱 추가 전 반드시 커스텀 미들웨어 추가Mvc()를 사용합니다.
appsettings.json 파일에서 사용자 이름, 암호를 읽는 동안 정적 읽기 전용 속성을 시작 파일에 추가합니다.그런 다음 appsettings.json에서 읽습니다.마지막으로, 프로젝트의 모든 위치에서 값을 읽습니다.예:
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } public static string UserNameFromAppSettings { get; private set; } public static string PasswordFromAppSettings { get; private set; } //set username and password from appsettings.json UserNameFromAppSettings = Configuration.GetSection("BasicAuth").GetSection("UserName").Value; PasswordFromAppSettings = Configuration.GetSection("BasicAuth").GetSection("Password").Value; }
이 공용 Githubrepo https://github.com/boskjoett/BasicAuthWebApi 에서는 기본 인증으로 보호되는 엔드포인트가 있는 ASP.NET Core 2.2 웹 API의 간단한 예를 볼 수 있습니다.
ASP.NET Core 2.0(Angular 포함)
인증 필터 유형을 사용해야 합니다.
[Authorization(인증 체계) = JwtBearerDefaults.인증 체계)]
언급URL : https://stackoverflow.com/questions/38977088/asp-net-core-web-api-authentication
'programing' 카테고리의 다른 글
테이블 크기 조정 방법UI 테이블 뷰의 머리글 뷰? (0) | 2023.06.01 |
---|---|
MongoDB에서 내부 어레이 크기를 쿼리하는 중 (0) | 2023.06.01 |
웹 애플리케이션이 iOS 기기에 푸시 알림을 보내는 방법은 무엇입니까? (0) | 2023.06.01 |
배열을 하나의 문자열로 결합하는 루비 (0) | 2023.06.01 |
iPhone 앱에 대한 Facebook 액세스 토큰 서버 측 검증 (0) | 2023.06.01 |