Spring boot 1.x в Spring boot 2.x
Когда я использую Spring Boot 1.x в приложении, защищенном с помощью Spring, я использую GenericFilterBean
для перехвата повторного получения и проверки его токена в другом сервисе, используя REST с restTemplate для проверки токена на сервере аутентификации. Я получаю следующий ответ когда я использую недопустимый токен, появляется следующее сообщение об ошибке 500:
{
"timestamp": 1535838247986,
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.web.client.HttpClientErrorException",
"message": "401 Unauthorized",
"path": "/ users"
}
Ошибка консоли:
org.springframework.web.client.HttpClientErrorException $ Unauthorized: 401 Unauthorized
at org.springframework.web.client.HttpClientErrorException.create (HttpClientErrorException.java:81) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
at org.springframework.web.client.DefaultResponseErrorHandler.handleError (DefaultResponseErrorHandler.java:97) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
at org.springframework.web.client.DefaultResponseErrorHandler.handleError (DefaultResponseErrorHandler.java:79) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
at org.springframework.web.client.ResponseErrorHandler.handleError (ResponseErrorHandler.java:63) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
at org.springframework.web.client.RestTemplate.handleResponse (RestTemplate.java:777) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
at org.springframework.web.client.RestTemplate.doExecute (RestTemplate.java:735) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
at org.springframework.web.client.RestTemplate.execute (RestTemplate.java:669) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
at org.springframework.web.client.RestTemplate.exchange (RestTemplate.java:578) ~ [spring-web-5.1.0.RC2.jar: 5.1.0.RC2]
Пока все хорошо.
Но когда я использую мезокод с spring boor 2, api возвращает страницу ошибки 500:
<! doctype html> <html lang = "en"> <head> <title> HTTP Status 500 - Internal Server Error h1 {font-family: Tahoma, Arial, sans-serif; color: white; background-color: # 525D76; font-size: 22px;} h2 {font-family: Tahoma, Arial, sans-serif; : Tahoma, Arial, sans-serif; color: white; background-color: # 525D76; font-size: 14px;} body {font-family: Tahoma, Arial, sans-serif; color: black; background-color: white;} b {font-family: Tahoma, Arial, sans-serif; color: white; background-color: # 525D76;} p {font-family: Tahoma, Arial, sans-serif ; background: color; black; font-size: 12px;} a {color: black;} a.name {color: black;} .line {height: 1px; background-color: # 525D76; border: none; </ h1> </ body> </ body> </ h1>
Ошибка консоли:
org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
at org.springframework.web.client.DefaultResponseErrorHandler.handleError (DefaultResponseErrorHandler.java:91) ~ [spring-web-4.3.7.RELEASE.jar: 4.3.7.RELEASE]
at org.springframework.web.client.RestTemplate.handleResponse (RestTemplate.java:700) ~ [spring-web-4.3.7.RELEASE.jar: 4.3.7.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute (RestTemplate.java:653) ~ [spring-web-4.3.7.RELEASE.jar: 4.3.7.RELEASE]
at org.springframework.web.client.RestTemplate.execute (RestTemplate.java:613) ~ [spring-web-4.3.7.RELEASE.jar: 4.3.7.RELEASE]
at org.springframework.web.client.RestTemplate.exchange (RestTemplate.java:531) ~ [spring-web-4.3.7.RELEASE.jar: 4.3.7.RELEASE]
Код: WebSecurityConfig
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.anyRequest().authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in header
.addFilterBefore(new JWTAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// Create a default account
auth.inMemoryAuthentication()
.withUser("admin")
.password("password")
.roles("ADMIN");
}
}
Код: TokenAuthenticationService
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.client.RestTemplate;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import static java.util.Collections.emptyList;
class TokenAuthenticationService {
static final long EXPIRATIONTIME = 864_000_000; // 10 days
static final String SECRET = "ThisIsASecret";
static final String TOKEN_PREFIX = "Bearer";
static final String HEADER_STRING = "Authorization";
static void addAuthentication(HttpServletResponse res, String username) {
String JWT = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
}
static Authentication getAuthentication(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token != null) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_JSON);
header.add("Authorization", token);
HttpEntity<String> entity = new HttpEntity<>("parameters", header);
restTemplate.exchange("http://http://www.mocky.io/v2/5b8b11362c0000eb15281054", HttpMethod.GET, entity, String.class);// this request return 401 and, in this moment a app render error
String user ="";
return user != null ?
new UsernamePasswordAuthenticationToken(emptyList(), user, null) :
null;
}
return null;
}
}
Этот запрос возвращает 401, и в этот момент приложение выдает ошибку
restTemplate.exchange("http://http://www.mocky.io/v2/5b8b11362c0000eb15281054", HttpMethod.GET, entity, String.class);
Единственное отличие в этом коде - версия с загрузочной пружиной.
В чем причина такого поведения?
Как заставить весеннюю загрузку 2 правильно вернуть ошибку API?