I'm trying to get the exact motive for a failed autentication (i.e wrong password, user doesn't exist, and so on) problem is, no matter how I try do simulate this actions I always get "Full authentication is required to access this resource", how can I get a more detailed exception ? TKS in advance !
Here's my code:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
UserService userService;
#Autowired
UnauthorizedCustomResponse unauthorizedCustomResponse;
#Autowired
AccessDeniedCustomResponse accessDeniedCustomResponse;
#Autowired
CryptographyService cryptographyService;
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(userService)
.passwordEncoder(cryptographyService.getCryptography());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/auth/signin", "/api/public/**", "/api/private/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedCustomResponse)
.accessDeniedHandler(accessDeniedCustomResponse)
.and()
.httpBasic();
}
}
#Component
public class AccessDeniedCustomResponse implements AccessDeniedHandler {
private final Logger logger = LogManager.getLogger(this.getClass());
#Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception)
throws IOException, ServletException {
logger.error("Usuário não autenticado: {}", exception.getMessage());
CustomException customException = new CustomException(CustomExceptionMessage.CUSTOM_EXCEPTION_NOT_MAPPED, exception);
customException.flush(response);
}
}
#Component
public class UnauthorizedCustomResponse implements AuthenticationEntryPoint {
private final Logger logger = LogManager.getLogger(this.getClass());
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
logger.error("Acesso não autorizado: {}", exception.getMessage());
CustomException customException = new CustomException(CustomExceptionMessage.ACCESS_DENIED, exception);
customException.flush(response);
}
}
You can analyze the specific exception that was thrown from the AuthenticationException superclass and act accordingly:
#Component
public class UnauthorizedCustomResponse implements AuthenticationEntryPoint {
private final Logger logger = LogManager.getLogger(this.getClass());
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if(exception.getClass().isAssignableFrom(UsernameNotFound.class)) {
//Username not found
}
else if (exception.getClass().isAssignableFrom(BadCredentials.class)) {
//Bad credentials error
}
else if (exception.getClass().isAssignableFrom(AccountStatusException.class)) {
//Accound status exception
}
logger.error("Acesso não autorizado: {}", exception.getMessage());
CustomException customException = new CustomException(CustomExceptionMessage.ACCESS_DENIED, exception);
customException.flush(response);
}
}
You can find a better list of AuthenticationException known subclasses here: https://docs.spring.io/spring-security/site/docs/4.2.19.RELEASE/apidocs/org/springframework/security/core/AuthenticationException.html
Related
Is it possible not to redirect to a view without query parameters? I have a login view and I want to redirect to login?error url in browser when login fails. I have my own AuthenticationFailureHandler:
public class SomeCustomHandler implements AuthenticationFailureHandler {
private final SimpleUrlAuthenticationFailureHandler authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler("/login?error");
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
authenticationFailureHandler.onAuthenticationFailure(request, response, exception);
}
}
configured in WebSecurityConfigurerAdapter:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/login", "/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureHandler(new SomeCustomHandler())
.permitAll();
}
But when login fails, returned login?error is redirected in user to login ignoring ?error parameter.
Here is my MvcWebConfigurer:
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login/**").setViewName("login");
}
I think you can try to do something like that:
public class SomeCustomHandler implements AuthenticationFailureHandler {
private final SimpleUrlAuthenticationFailureHandler authenticationFailureHandler = new SimpleUrlAuthenticationFailureHandler("/login?error");
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
if(request.getPathInfo().startsWith("/login") && !request.getParameterMap().isEmpty()) {
authenticationFailureHandler.setUseForward(true);
}
authenticationFailureHandler.onAuthenticationFailure(request, response, exception);
}
}
I'm writing test for a Rest API controller. This endpoint is accessible without any authorization:
#EnableWebSecurity
#Configuration
#Import(AppConfig.class)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsRepository accountRepository;
#Autowired
private CustomUserDetailsService customUserDetailsService;
#Autowired
private JWTAuthenticationFilter jwtAuthenticationFilter;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().authenticated().and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
/*
* Apparently, permitAll() doesn't work for custom filters, therefore we ignore the signup and login endpoints
* here
*/
#Override
public void configure(WebSecurity web)
throws Exception {
web.ignoring()
.antMatchers(HttpMethod.POST, "/login")
.antMatchers(HttpMethod.POST, "/signup");
}
/*
* set user details services and password encoder
*/
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/* Stopping spring from adding filter by default */
#Bean
public FilterRegistrationBean rolesAuthenticationFilterRegistrationDisable(JWTAuthenticationFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean(filter);
registration.setEnabled(false);
return registration;
}
}
The JWTAuthenticationFilter class:
#Component
public class JWTAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
#Autowired
private UserDetailsService customUserDetailsService;
private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
private final static UrlPathHelper urlPathHelper = new UrlPathHelper();
final static String defaultFilterProcessesUrl = "/**";
public JWTAuthenticationFilter() {
super(defaultFilterProcessesUrl);
super.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(defaultFilterProcessesUrl)); //Authentication will only be initiated for the request url matching this pattern
setAuthenticationManager(new NoOpAuthenticationManager());
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
Authentication authentication = AuthenticationService.getAuthentication(request, customUserDetailsService);
return getAuthenticationManager().authenticate(authentication);
}
#Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
logger.debug("failed authentication while attempting to access "+ urlPathHelper.getPathWithinApplication((HttpServletRequest) request));
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Authentication Failed");
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
super.doFilter(req, res, chain);
}
}
When I make a request (using postman) to 'signup' endpoint it works fine. But when I run the test, it hits doFilter and fails, as it doesn't get authenticated.
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class AuthenticationControllerFTest {
#Autowired
private MockMvc mockMvc;
#MockBean
private AuthenticationManager authenticationManager;
#Test
public void testCreate() throws Exception {
Authentication authentication = Mockito.mock(Authentication.class);
Mockito.when(authentication.getName()).thenReturn("DUMMY_USERNAME");
Mockito.when(
authenticationManager.authenticate(Mockito
.any(UsernamePasswordAuthenticationToken.class)))
.thenReturn(authentication);
String exampleUserInfo = "{\"name\":\"Test1234\",\"username\":\"test#test.com\",\"password\":\"Salam12345\"}";
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/signup")
.accept(MediaType.APPLICATION_JSON).content(exampleUserInfo)
.contentType(MediaType.APPLICATION_JSON);
MvcResult result = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = result.getResponse();
int status = response.getStatus();
String content = response.getContentAsString();
System.out.println(content);
Assert.assertEquals("http response status is wrong", 200, status);
}
}
Any idea on how to fix this issue ?
The issue was resolved by adding the following code to the test class:
#Autowired
private WebApplicationContext context;
#Autowired
private Filter springSecurityFilterChain;
#Before
public void setup() {
mockMvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(springSecurityFilterChain).build();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated();
}
I have rest api application in Spring Boot 1.5.3, I'm using security to login and authenticate every request by token to my api. I want add my custom exception with unauthorized exception when user not found by token. Class with exception is added but every response has 500 code but I want 401 response code. Belowe is my code.
StatelessAuthenticationFilter
public class StatelessAuthenticationFilter extends GenericFilterBean {
private final TokenAuthenticationService tokenAuthenticationService;
public StatelessAuthenticationFilter(TokenAuthenticationService taService) {
this.tokenAuthenticationService = taService;
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(tokenAuthenticationService.getAuthentication((HttpServletRequest) req));
chain.doFilter(req, res);
}
StatelessLoginFilter
public class StatelessLoginFilter extends AbstractAuthenticationProcessingFilter {
private final TokenAuthenticationService tokenAuthenticationService;
private final UserServiceImpl userService;
public StatelessLoginFilter(String urlMapping, TokenAuthenticationService tokenAuthenticationService,
UserServiceImpl userDetailsService, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(urlMapping));
this.userService = userDetailsService;
this.tokenAuthenticationService = tokenAuthenticationService;
setAuthenticationManager(authManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String headerCredentials = request.getHeader("BasicAuth");
if (headerCredentials == null) {
throw new BadCredentialsException("No header in request");
}
String credentials = new String(Base64.decodeBase64(headerCredentials), "UTF-8");
if (!credentials.contains((":"))) {
throw new BadCredentialsException("Wrong header");
}
String [] credentialsArray = credentials.split(":");
String login = credentialsArray[0];
String password = credentialsArray[1];
final UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(login, password);
return getAuthenticationManager().authenticate(loginToken);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authentication) throws IOException, ServletException {
// Lookup the complete User2 object from the database and create an Authentication for it
final User authenticatedUser = userService.loadUserByUsername(authentication.getName());
final UserAuthentication userAuthentication = new UserAuthentication(authenticatedUser);
// Add the custom token as HTTP header to the response
tokenAuthenticationService.addAuthentication(response, userAuthentication);
// Add the authentication to the Security context
SecurityContextHolder.getContext().setAuthentication(userAuthentication);
}
MyOwnException
public class MyOwnException extends RuntimeException {
public MyOwnException(String message) {
super(message);
}
RestResponseEntityExceptionHandler
#ControllerAdvice
public class RestResponseEntityExceptionHandler extends DefaultHandlerExceptionResolver {
#ExceptionHandler(MyOwnException.class)
void handleMyOwnException(HttpServletResponse response) throws IOException {
response.sendError(HttpStatus.UNAUTHORIZED.value());
}
}
StatelessAuthenticationSecurityConfig
#EnableWebSecurity
#Configuration
#Order(1)
public class StatelessAuthenticationSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserServiceImpl userService;
#Autowired
private TokenAuthenticationService tokenAuthenticationService;
public StatelessAuthenticationSecurityConfig() {
super(true);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().hasRole("USER")
.anyRequest().hasRole("ADMIN").and()
// custom JSON based authentication by POST of {"username":"<name>","password":"<password>"} which sets the token header upon authentication
.addFilterBefore(new StatelessLoginFilter("/login", tokenAuthenticationService, userService, authenticationManager()), UsernamePasswordAuthenticationFilter.class)
// custom Token based authentication based on the header previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*");
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "DELETE", "OPTIONS"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
configuration.addAllowedHeader("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
protected UserServiceImpl userDetailsService() {
return userService;
}
VoteApp
#SpringBootApplication
public class VoteApp {
public static void main(String[] args) {
SpringApplication.run(VoteApp.class, args);
}
#Bean
public Filter characterEncodingFilter() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}
}
UserServiceImpl
#Service
public class UserServiceImpl implements org.springframework.security.core.userdetails.UserDetailsService {
#Autowired
private UserRepository userRepository;
#Override
public final User loadUserByUsername(String username) throws UsernameNotFoundException {
final User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("user not found");
}
return user;
}
public User findByToken(String token) throws MyOwnException {
final User user = userRepository.findByToken(token);
if (user == null) {
throw new MyOwnException("user by token not found");
}
return user;
}
public void save(User user) {
userRepository.save(user);
}
}
Obviously #ControllerAdvice can't handle your exception because controller methods has not been called yet. I mean you exception being thrown in servlet filter. I think you going to have to catch it manually, smth like this:
public class StatelessAuthenticationFilter extends GenericFilterBean {
private final TokenAuthenticationService tokenAuthenticationService;
public StatelessAuthenticationFilter(TokenAuthenticationService taService) {
this.tokenAuthenticationService = taService;
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
Authentication auth = null;
try {
auth = tokenAuthenticationService.getAuthentication((HttpServletRequest) req);
} catch (MyOwnException e) {
SecurityContextHolder.clearContext();
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
return;
}
SecurityContextHolder.getContext().setAuthentication(auth);
chain.doFilter(req, res);
}
Add #ResponseStatus annotation to your exception handler of controller advice.
For more information visit - Exception Handling in Spring MVC
I am implementing custom 'AuthenticationProvider'. If not authenticated I am throwing exception inside 'authenticate' function as shown below.
public class DelegatingLdapAuthenticationProvider implements AuthenticationProvider {
private ActiveDirectoryLdapAuthenticationProvider primaryProvider;
private List<ActiveDirectoryLdapAuthenticationProvider> secondaryProviders = new ArrayList<>();
public DelegatingLdapAuthenticationProvider() {
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Authentication result = null;
AuthenticationException exception = null;
try {
result = primaryProvider.authenticate(authentication);
} catch (AuthenticationException e) {
exception = e;
for (ActiveDirectoryLdapAuthenticationProvider secondaryProvider : secondaryProviders) {
try {
result = secondaryProvider.authenticate(authentication);
if (result.isAuthenticated()) {
break;
}
} catch (AuthenticationException e1) {
exception = e;
}
}
}
if (result == null || !result.isAuthenticated()) {
throw exception;
}
return result;
}
I have global exception handler as shown below.
#ControllerAdvice
public class GlobalExceptionHandler {
#ExceptionHandler({NoPermissionException.class})
#ResponseBody
#ResponseStatus(value = HttpStatus.FORBIDDEN)
public Map<String, String> noPermission(NoPermissionException e) {
return createErrorResponse(e, "Don't have permissions");
}
#ExceptionHandler({Exception.class})
#ResponseBody
#ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public Map<String, String> exceptionInProcessing(Exception e) {
return createErrorResponse(e, "Unable to process. Unknown error occurred: " + e.getMessage());
}
private Map<String, String> createErrorResponse(Exception e, String errorMessage) {
Map<String, String> errorResponse = new HashMap<>();
errorResponse.put("message", errorMessage);
errorResponse.put("reason", e.toString());
return errorResponse;
}
}
When exception is thrown inside the 'authenticate' function, global exception handler is not being called. For all the other exceptions it is being called. I want to catch the exception inside global exception handler and return custom error message. How can I do that? Any help appreciated. Thanks in advance.
The GlobalExceptionHandler is for controller exception handler, but the AuthenticationProvider is still in filter, if you want to handler the AuthenticationException, you need to handle it to implement AuthenticationEntryPoint and override the commence method.
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException
AuthenticationException and AccessDeniedException have already been handled by ExceptionTranslationFilter. You just need to inject AuthenticationEntryPoint and AccessDeniedHandler(which handle AccessDeniedException)
Or you can catch these exception in filter and then handle it in filer, like AuthenticationFailureHandler in AbstractAuthenticationProcessingFilter
To complement the #chaoluo answer:
Implement the AuthenticationEntryPoint interface and resolve the exception by HandlerExceptionResolver:
#Component("restAuthenticationEntryPoint")
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint, AccessDeniedHandler {
#Autowired
private HandlerExceptionResolver resolver;
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) {
resolver.resolveException(request, response, null, exception);
}
}
Inject the RestAuthenticationEntryPoint into your WebSecurityConfigurerAdapter implementation and use it as the authenticationEntryPoint:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthenticationEntryPoint authenticationEntryPoint;
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.and()
.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.and()
.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
Now because we resolved the exception by HandlerExceptionResolver, we can use the typical Spring Web error handling using #ControllerAdvice and #ExceptionHandler annotations:
#RestControllerAdvice
public abstract class ErrorsControllerAdvice {
#ExceptionHandler
public ResponseEntity<?> handleException(Throwable exception, WebRequest webRequest, Locale locale) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED);
}
}
Authentication provider is called before controller exception handler has a chance to catch exceptions.
You can override AuthenticationFailureHandler to handle exceptions on security filter chain level, look at the examples
The behavior as described in documentation:
The filter calls the configured AuthenticationManager to process each authentication request. The destination following a successful authentication or an authentication failure is controlled by the AuthenticationSuccessHandler and AuthenticationFailureHandler strategy interfaces, respectively. The filter has properties which allow you to set these so you can customize the behaviour completely
As #chaoluo already said you need to implement AuthenticationEntryPoint and override the commence method. If you want to return an error JSON object you can do the following:
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
//create errorObj
PrintWriter writer = response.getWriter();
mapper.writeValue(writer, errorObj);
writer.flush();
}
I have a org.springframework.web.filter.GenericFilterBean filter. I would like to throw an exception when user is not authorized and catch this exception with #ControllerAdvice. But it seems that the handler doesn't do that.
Filter method
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
ClientAuthentication auth = (ClientAuthentication) authenticationService.getAuthentication(httpRequest, httpResponse);
SecurityContextHolder.getContext().setAuthentication(auth);
if (auth.isAuthenticated()) {
chain.doFilter(request, response);
} else {
ObjectMapper mapper = new ObjectMapper();
response.setCharacterEncoding("UTF-8");
httpResponse.getWriter().write(mapper.writeValueAsString(auth.getInfo()));
}
}
It works but a disadvantage is that I want to catch exception and render exception message back to the client with respect to Content-Type and Accept HTTP header. This solution renders what I want but into JSON only and my application has to handle XML and JSON.
Exception handler
it works when I throw exceptions from #Controller or #RestController but not from HTTP filter.
#ControllerAdvice
class GlobalExceptionHandler {
private static final Logger LOGGER = LogManager.getLogger(GlobalExceptionHandler.class);
#ExceptionHandler(BadRequestException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
public
#ResponseBody
ResponseMessage badRequestException(BadRequestException ex) {
return ex.getResponseMessage();
}
/** rest omitted .... **/
}
Update #1
This is my Spring Security config where AuthFilter filter is set.
#EnableWebSecurity
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Configuration
#Order(1)
public static class ApiSecurity extends WebSecurityConfigurerAdapter {
private static Logger LOG = LogManager.getLogger(ApiSecurity.class);
#Bean
AuthenticationEntryPoint authenticationEntryPoint() {
LOG.debug("authenticationEntryPoint bean");
return new RestAuthenticationEntryPoint();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
.and()
.servletApi()
.and()
.headers().cacheControl();
http.antMatcher(ApiController.API_ROOT + "/**").authorizeRequests().anyRequest().authenticated()
.and()
.addFilterBefore(new AuthFilter(), UsernamePasswordAuthenticationFilter.class);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(ApiController.API_ROOT + "/sandbox/**");
}
}
#Configuration
public static class WebFormSecurity extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService defaultUserService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(defaultUserService).passwordEncoder(passwordEncoder);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/public/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
.loginPage("/login").failureUrl("/login?error").permitAll().and()
.logout().permitAll();
}
}
}