@ExceptionHandler Regardless spring security oauth2 custom exception interception InternalAuthenticationServiceException

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/c5113620/article/details/89576545

Since the principle of spring security authentication is registered to the filter chain by tomcat container, so that the authentication can not pass through the DispatcherServlet abnormality, it is not treated @ExceptionHandler

//AuthenticationEntryPoint
{
    "error": "unauthorized",
    "error_description": "Full authentication is required to access this resource"
}
或者
//AccessDeniedHandler
{
    "error": "invalid_token",
    "error_description": "Invalid access token: 82b47091-c752-4832-b5dd-96a4da4df999"
}

{
    "error": "access_denied",
    "error_description": "not allowed access"
}

spring security oauth2 divided into two: the authentication server and resource server
authentication server is ** / oauth / token ** Sign in to get the authentication token
server resources, is to manage those resources need to be checked url authentication and access control, resource server configures ResourceServerConfiguration url need to check permissions

Sometimes configured authentication server, you can get token, but is still being given access to resources url access_denied, try the following configuration
spring-boot-starter-parent from 1.4.2 to 1.5.2-OAuth2-access_denied

//下面的order值看OAuth2 版本
security.oauth2.resource.filter-order = 3
或者
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) on WebSecurityConfigurerAdapter class

So spring security oauth2 exception will appear in two

  • When the login authentication / oauth / token token acquisition
  • When accessing other resources url

So you need to configure two custom exception

@Configuration
@EnableAuthorizationServer
public class OAuthSecurityConfig extends AuthorizationServerConfigurerAdapter {
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        //自定义 /oauth/token 异常处理
        endpoints.exceptionTranslator(new MyWebResponseExceptionTranslator());
    }
}

@Configuration
@EnableResourceServer
public  class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            //自定义资源访问认证异常,没有token,或token错误,使用MyAuthenticationEntryPoint
            resources.authenticationEntryPoint(new MyAuthenticationEntryPoint());
            resources.accessDeniedHandler(new MyAccessDeniedHandler());
        }
}
//实现更加用户名获取用户信息
@Component
public class UserDetailServiceImpl implements UserDetailsService {
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        if(user==null)
            // throw OAuth2Exception.create(OAuth2Exception.INVALID_REQUEST, "无此用户名");
            throw new UsernameNotFoundException("无此用户名");
    }
}

// 默认处于安全,会把UsernameNotFoundException转为BadCredentialsException,就是 “坏的凭据”,注入下面配置的bean
@Bean
    public AuthenticationProvider daoAuthenticationProvider(UserDetailsService userDetailsService) {
        DaoAuthenticationProvider impl = new DaoAuthenticationProvider();
        impl.setUserDetailsService(userDetailsService);
        impl.setHideUserNotFoundExceptions(false) ;
        return impl ;
    }

For the login authentication configuration exception handling, then the process type, by custom WebResponseExceptionTranslator into OAuth2Exception, then custom serialization json class, to achieve the purpose custom exception information Jackson.

OAuth2Exception itself is inherited RuntimeException, and is OAuth2ExceptionJackson1Serializer serialized, so all we do is custom serialization and a OAuth2Exception subclass of this subclass

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;

/**
 * @author zhanghui
 * @date 2019/6/21
 */
public class MyWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
    @Override
    public ResponseEntity<OAuth2Exception> translate(Exception exception) throws Exception {
        if (exception instanceof OAuth2Exception) {
            OAuth2Exception oAuth2Exception = (OAuth2Exception) exception;
            return ResponseEntity
                    .status(oAuth2Exception.getHttpErrorCode())
                    .body(new CustomOauthException(oAuth2Exception.getMessage()));
        }else if(exception instanceof AuthenticationException){
            AuthenticationException authenticationException = (AuthenticationException) exception;
            return ResponseEntity
                    .status(HttpStatus.UNAUTHORIZED)
                    .body(new CustomOauthException(authenticationException.getMessage()));
        }
        return ResponseEntity
                .status(HttpStatus.OK)
                .body(new CustomOauthException(exception.getMessage()));
    }
}
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;

/**
 * @author zhanghui
 * @date 2019/6/21
 */
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {
    public CustomOauthException(String msg) {
        super(msg);
    }
}
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;

/**
 * @author zhanghui
 * @date 2019/6/21
 */
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException> {

    public CustomOauthExceptionSerializer() {
        super(CustomOauthException.class);
    }

    @Override
    public void serialize(CustomOauthException value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeNumberField("code4444", value.getHttpErrorCode());
        jsonGenerator.writeBooleanField("status", false);
        jsonGenerator.writeObjectField("data", null);
        jsonGenerator.writeObjectField("errors", Arrays.asList(value.getOAuth2ErrorCode(),value.getMessage()));
        if (value.getAdditionalInformation()!=null) {
            for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) {
                String key = entry.getKey();
                String add = entry.getValue();
                jsonGenerator.writeStringField(key, add);
            }
        }
        jsonGenerator.writeEndObject();
    }
}

Custom anomaly for access to resources

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhanghui
 * @date 2019/6/21
 */
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException)
            throws ServletException {

        Map map = new HashMap();
        map.put("errorentry", "401");
        map.put("message", authException.getMessage());
        map.put("path", request.getServletPath());
        map.put("timestamp", String.valueOf(new Date().getTime()));
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(response.getOutputStream(), map);
        } catch (Exception e) {
            throw new ServletException();
        }
    }

}
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhanghui
 * @date 2019/6/21
 */
public class MyAccessDeniedHandler implements AccessDeniedHandler{
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setContentType("application/json;charset=UTF-8");
        Map map = new HashMap();
        map.put("errorauth", "400");
        map.put("message", accessDeniedException.getMessage());
        map.put("path", request.getServletPath());
        map.put("timestamp", String.valueOf(new Date().getTime()));
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        try {
            ObjectMapper mapper = new ObjectMapper();
            mapper.writeValue(response.getOutputStream(), map);
        } catch (Exception e) {
            throw new ServletException();
        }
    }
}

Guess you like

Origin blog.csdn.net/c5113620/article/details/89576545