[转]实现oauth自定义Exception

OAuth实现自定义Exception

前言

自己在查找相关问题时发现清一色连代码都不看一下的转载,真的看吐了,以下是自己根据git源码修改部分不正确代码以及部分业务,与源码有部分出入,建议直接看源码


自定义登录失败异常信息

新增CustomOauthException

  • 添加自定义异常类,指定json序列化方式
@JsonSerialize(using=CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception {
    public CustomOauthException(String msg) {
        super(msg);
    }
}

新增CustomOauthExceptionSerializer

  • 添加CustomOauthException的序列化实现
public class CustomOauthExceptionSerializer extends StdSerializer {
    public CustomOauthExceptionSerializer() {
        super(CustomOauthException.class);
    }

    @Override
    public void serialize(CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        gen.writeStartObject();
        gen.writeStringField("error", String.valueOf(value.getHttpErrorCode()));
        gen.writeStringField("message", value.getMessage());
        gen.writeStringField("path", request.getServletPath());
        gen.writeStringField("timestamp", String.valueOf(System.currentTimeMillis()));
        if (value.getAdditionalInformation()!=null) {
            for (Map.Entry entry : value.getAdditionalInformation().entrySet()) {
                String key = entry.getKey();
                String add = entry.getValue();
                gen.writeStringField(key, add);
            }
        }
        gen.writeEndObject();
    }
}

添加CustomWebResponseExceptionTranslator

  • 添加CustomWebResponseExceptionTranslator,登录发生异常时指定exceptionTranslator
@Component("customWebResponseExceptionTranslator")
public class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
    @Override
    public ResponseEntity translate(Exception e) throws Exception {

        OAuth2Exception oAuth2Exception = (OAuth2Exception) e;
        return ResponseEntity
                .status(oAuth2Exception.getHttpErrorCode())
                .body(new CustomOauthException(oAuth2Exception.getMessage()));
    }
}

修改AuthorizationConfig

  • 指定自定义customWebResponseExceptionTranslator
    @Autowired
    private AuthenticationManager auth;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        List tokenGranters = getTokenGranters(endpoints.getTokenServices(), endpoints.getClientDetailsService(), endpoints.getOAuth2RequestFactory());
        endpoints.tokenGranter(new CompositeTokenGranter(tokenGranters));
        endpoints.tokenEnhancer((oAuth2AccessToken, oAuth2Authentication) -> oAuth2AccessToken);
        endpoints.authenticationManager(auth).tokenStore(tokenStore());
        endpoint
        s.exceptionTranslator(new CustomWebResponseExceptionTranslator());
    }
    
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.authenticationEntryPoint(new AuthExceptionEntryPoint());
    }
    
    /**
     * 配置客户端一些信息
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        InMemoryClientDetailsServiceBuilder build = clients.inMemory();
        if (ArrayUtils.isNotEmpty(oAuth2Properties.getClients())) {
            for (OAuth2ClientProperties config : oAuth2Properties.getClients()) {
                build.withClient(config.getClientId())
                        .secret(config.getClientSecret())
                        .accessTokenValiditySeconds(config.getAccessTokenValiditySeconds())
                        .refreshTokenValiditySeconds(60 * 60 * 24 * 15)
                        //OAuth2支持的验证模式
                        .authorizedGrantTypes("refresh_token", "password", "authorization_code")
                        .scopes("all");
            }
        }
    }
    
    //自定义验证Service
    private List getTokenGranters(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
            return Lists.newArrayList(
                    new XXXCustomTokenGranter(tokenServices, clientDetailsService, requestFactory, customUserDetailsService),
                    new XXXCustomTokenGranter(tokenServices, clientDetailsService, requestFactory, customUserDetailsService),
                    new XXCustomTokenGranter(tokenServices, clientDetailsService, requestFactory, customUserDetailsService));
    }

自定义Token异常信息

添加AuthExceptionEntryPoint

  • 自定义AuthExceptionEntryPoint用于tokan校验失败返回信息
public class AuthExceptionEntryPoint implements AuthenticationEntryPoint {


    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException)
            throws  ServletException {

        Map map = new HashMap();
        map.put("error", "401");
        map.put("message", authException.getMessage());
        map.put("path", request.getServletPath());
        map.put("timestamp", String.valueOf(System.currentTimeMillis()));
        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();
        }
    }
}

添加CustomAccessDeniedHandler

  • 授权失败(forbidden)时返回信息
@Component("customAccessDeniedHandler")
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    @Autowired
    private ObjectMapper objectMapper;

    @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("error", "400");
            map.put("message", accessDeniedException.getMessage());
            map.put("path", request.getServletPath());
            map.put("timestamp",String.valueOf(System.currentTimeMillis()));
            response.setContentType("application/json");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.getWriter().write(objectMapper.writeValueAsString(map));
    }
}

修改ResourceServerConfig

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.authenticationEntryPoint(new AuthExceptionEntryPoint())
                .accessDeniedHandler(new CustomAccessDeniedHandler());
    }
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                //登录成功处理器
                .successHandler(appLoginInSuccessHandler)
                .failureHandler(appLoginFailureHandler)
                .and()
                //添加自定义handler
                .exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint())
                .and()
                .apply(permitAllSecurityConfig)
                .and()
                .authorizeRequests()
                .antMatchers("/user").hasRole("USER")
                .antMatchers("/forbidden").hasRole("ADMIN")
                .antMatchers("/permitAll").permitAll()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }

原git地址

你可能感兴趣的:(java,spring,springboot,oauth)