Return RESTful/json response instead of login form in Spring boot OAUTH2

淺唱寂寞╮ 提交于 2019-12-24 11:23:25

问题


I'm struggling to return a json response when the user is nog logged in, instead of returning a html login form.

The application is only using @RestController's and I do not want any web support.

    http
        .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .httpBasic().disable();

When I do a get request using the browser or postman, I receive back the default spring HTML login form.

security.basic.enabled=true

I'm using OATH2, and when I request a token it works great and I get a response like this:

{
  "access_token": "227803d1-fe94-4e31-b496-3a03bafb9479",
  "token_type": "bearer",
  "refresh_token": "322f4ee9-4c48-4e06-a129-f4b6af93d664",
  "expires_in": 43199,
  "scope": "read write"
}

Somehow, it works correct in this example:

https://github.com/royclarkson/spring-rest-service-oauth

And when I'm not authorized, I want back something like this:

{
  "error": "unauthorized",
  "error_description": "An Authentication object was not found in the SecurityContext"
}

But I'm getting a login form, and I want the response above. What am I doing wrong? I litterally can't uderstand why it works in the GitHub example, and not in my case. Is there a way to completely disable the login form, and force the json response?


回答1:


AuthenticationEntryPoint is used for exception handling in spring security.

If you have added the oauth2 to your pom, you can use OAuth2AuthenticationEntryPoint for you entry point, the Entry point is for spring security exception handling, if you are using the basic for your authentication, you can config like this

http
  .httpBasic().authenticationEntryPoint(getCustomerEntryPoint());

@Bean
protected AuthenticationEntryPoint getCustomerEntryPoint() {
    return new OAuth2AuthenticationEntryPoint();
}

as you can see the exception handling in OAuth2AuthenticationEntryPoint

// Try to extract a SpringSecurityException from the stacktrace
    Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e);
    Exception ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType(
            OAuth2Exception.class, causeChain);

    if (ase != null) {
        return handleOAuth2Exception((OAuth2Exception) ase);
    }

    ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class,
            causeChain);
    if (ase != null) {
        return handleOAuth2Exception(new UnauthorizedException(e.getMessage(), e));
    }

    ase = (AccessDeniedException) throwableAnalyzer
            .getFirstThrowableOfType(AccessDeniedException.class, causeChain);
    if (ase instanceof AccessDeniedException) {
        return handleOAuth2Exception(new ForbiddenException(ase.getMessage(), ase));
    }

    ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer
            .getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain);
    if (ase instanceof HttpRequestMethodNotSupportedException) {
        return handleOAuth2Exception(new MethodNotAllowed(ase.getMessage(), ase));
    }

    return handleOAuth2Exception(new ServerErrorException(e.getMessage(), e));

it will try to get OAuth2Exception, AuthenticationException, AccessDeniedException in order, I think you can use this.

And you can also config the ExceptionTranslationFilter, this filter is in the spring security chain, and it will catch and handler the exception after it, like AuthenticationException, AccessDeniedException, and it is main entry point and will be helpful for most authentication method, like FormLogin.

http
  .exceptionHandling().authenticationEntryPoint(getCustomerEntryPoint());

If you are not use the spring oauth2, now you understand the AuthenticationEntryPoint, so you can also implement you own AuthenticationEntryPoint and custom your exception response, just overrider the commence method, like

BasicAuthenticationEntryPoint: it will return 'WWW-Authenticate' header LoginUrlAuthenticationEntryPoint: it will redirect to target url when no authentcation




回答2:


Will need a custom AuthenticationEntryPoint and override the commence() method.

Indeed, the entry point has to be registered in the Spring Security config

http.exceptionHandling()
                .authenticationEntryPoint(restAuthenticationEntryPoint)

Sample code:

public class UserAuthenticationEntryPoint implements
        AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException ex)
            throws IOException, ServletException {
        response.setContentType("application/json");
        response.getOutputStream().print("{\"error\":\"Unauthorized.. Please authenticate..\"}");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }
}


来源:https://stackoverflow.com/questions/43088456/return-restful-json-response-instead-of-login-form-in-spring-boot-oauth2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!