我正在尝试在Dotnet Core中进行过滤,以验证Login(Java)的其他Api中的令牌JWT 我做到了基本的是,因此,接收到令牌的过滤器将获取令牌Jwt并将其发送以进行验证 在其他Api中。我正在尝试做,但是我没有找到如何做到这一点。我确实用其他方法制作 但是我不知道该怎么做。
SendEmailController.cs类:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("[controller]")]
public class SendEmailController: ControllerBase
{
private readonly IEmailSender emailSender;
public SendEmailController(IEmailSender emailSender){
this.emailSender = emailSender;
}
[HttpPost]
public async Task<ActionResult> SendEmail(GetEmailDto emailDto) {
string header = Request.Headers["Authorization"];
string token = null;
if(header != null && header.Contains("Bearer")){
string [] aux = header.Split(" ");
token = aux.Length > 1 ? aux[1].Trim() : token;
}
if(token != null && await LoginService.ValidateToken(token) != null){
return Ok(this.emailSender.SendEmailAsync(emailDto));
} else {
return BadRequest("Email not sended >> ");
}
}
}
LoginService.cs:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
public class LoginService{
public static async Task<string> ValidateToken(string token)
{
try{
string tokenUrl = Environment.GetEnvironmentVariable("TOKEN_VALIDATE_URL");
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return await client.GetStringAsync(tokenUrl);
}
catch(Exception e)
{
Console.WriteLine("ERROR >> "+e.Message);
return null;
}
}
}
Startup.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using AutoMapper;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
namespace apiEmail
{
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.AddDbContext<DataContext>();
services.AddCors();
services.AddControllers();
services.AddAutoMapper(typeof(Startup));
services.AddScoped<IEmailService, EmailService>();
services.AddScoped<IAuthRepository, AuthRepository>();
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddMvc();
var key = Encoding.ASCII.GetBytes(Environment.GetEnvironmentVariable("SECRET_KEY")+" DOTNET DA DEPRESSAO");
services.AddAuthentication(x => {
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = false,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
}
private static void UpdateDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices
.GetRequiredService<IServiceScopeFactory>()
.CreateScope())
{
using (var context = serviceScope.ServiceProvider.GetService<DataContext>())
{
context.Database.Migrate();
}
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, DataContext context)
{
UpdateDatabase(app);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
//app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(
options => options
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
);
// app.UseAuthentication();
var options = new JwtBearerOptions
{
Audience = "...",
Authority = "...",
Events = new JwtBearerEvents
{
OnTokenValidated = context =>
{
// Add the access_token as a claim, as we may actually need it
var accessToken = context.SecurityToken as JwtSecurityToken;
if (accessToken != null)
{
Console.Write("Token >>", accessToken);
}
return Task.CompletedTask;
}
}
};
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
context.Database.EnsureCreated();
context.Database.Migrate();
}
}
}
如何执行验证而不留在Controller中,仅在 带有此类过滤器的startup.cs在Java中?
示例:
@Slf4j
@Component
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class JwtRequestFilter extends OncePerRequestFilter {
private JwtUtil jwtUtil;
private LoginService login;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
Users usr = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
if (jwtUtil.isTokenExpired(jwt)) {
throw new IOException("Token expirado ");
}
try {
usr = login.verifyToken(jwt);
Authentication auth = new UsernamePasswordAuthenticationToken(usr.getEmail(), usr.getSenha());
Set authorities = new HashSet<>();
authorities.add(new SimpleGrantedAuthority(usr.getTipo().toString()));
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken
= new UsernamePasswordAuthenticationToken(
auth.getName(), auth.getCredentials(), authorities);
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
} catch (Exception e) {
log.error("Error >> ", e);
throw new IOException("Erro ao validar o Token");
}
}
chain.doFilter(request, response);
}
}
LoginService.java类:
public class LoginService{
public Users verifyToken(String token) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer "+token);
HttpEntity<String> entity = new HttpEntity<String>(headers);
return restTemplate.exchange(Assets.API_TOKEN_DATA, HttpMethod.PUT, entity, Users.class).getBody();
}
}
谢谢
答案 0 :(得分:0)
@RafaelRfs我尝试将其发布为评论,但比受支持的要长,因此我将其发布为答案。
一旦您读到如果不考虑答案,请告诉我,我将删除它。
基本上,您需要一个秘密密钥和一种签名(算法)来生成JWT令牌。
在您的情况下,您在.NET Core上生成了该令牌,这完全没问题,然后您需要将此令牌发送到Java API,这也应该完全没问题。
从技术上讲,如果您在两个站点上使用相同的机密和相同的到期时间(.NET和Java),则在.NET端生成的令牌应在Java端完全可用。
我将严格根据我的观点做一些假设:
在Java方面,您应该使用中间件来接收该令牌,并且此中间件将为您进行处理(从授权标头中获得令牌)并对其进行解密而无需付出很大的努力。
我有一组微服务,我在身份微服务上生成了一个JWT,并且该JWT可以在所有其他微服务上正常使用。
即使使用相同的密钥,相同的算法和相同的到期时间,即使使用.NET App生成该JWT,您也可以在Java App上使用该JWT。
您应该尝试使用类似的中间件在Java端实现JWT。您的工作方式是编写大量的代码来完成以Java的几种方式完成的工作:https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/
实现JWT的所有最佳方法,您将不会在控制器上看到任何逻辑来解密令牌,也不必为此编写其他代码。您只是在某个时候设置了一些中间件。如果在这种情况下确实需要编码,则可以遵循此示例(具有Claims。在Microsoft Identity Framework + OAuth上也可以在.NET中找到相同的模型):https://developer.okta.com/blog/2018/10/31/jwts-with-java
其他:
我要恢复的通常是:
很抱歉,请长解释。希望有帮助。
答案 1 :(得分:0)
你会说葡萄牙语吗?谢谢你的回答,我认为是正确的 我将尝试在我的应用程序中实现相同的令牌和密钥。我刚在想 有必要在主应用程序中验证令牌, 多亏您的回答,现在我知道我不需要再次发送令牌才能在登录api中进行验证。我会尝试按照您所说的来实现。非常感谢您的答复,它对您有很大帮助!