在spring security前添加一个Filter

acdxxx188 发布于 02/14 20:48
阅读 111
收藏 1

请教大神,为什么我在增加一个filter后,能获取正常获取Oatuh2,但是为什么会出现unauthorized错误,前端能正常获取token,也显示错误

下面是我加的Filter,直接通过spring加载,没有在AuthorizationServerConfigurerAdapter里加载,因为我要加载到ClientCredentialsTokenEndpointFilter前面

功能是为spring security  oatuh2增加JSON解析的能力,拦截/oauth/token路径,把Body中的JSON转换成params

@Slf4j
@Component
@Order(value = Integer.MIN_VALUE)
public class JsonToUrlEncodedAuthenticationFilter implements Filter {
    private final ObjectMapper mapper;
    private final String filterProcessesUrl="/oauth/token";

    public JsonToUrlEncodedAuthenticationFilter(ObjectMapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    @SneakyThrows
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        log.debug("JSON过滤开始工作");
        if (!(request instanceof HttpServletRequest)) {
            throw new ServletException("just supports HTTP requests");
        }
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        if (new AntPathRequestMatcher(filterProcessesUrl, "POST").matches(httpRequest)){
            if (httpRequest.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
                    || httpRequest.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){
                log.debug("开始转换");
                InputStream is = httpRequest.getInputStream();
                try (BufferedReader br = new BufferedReader(new InputStreamReader(is), 16384)) {
                    String json = br.lines()
                            .collect(Collectors.joining(System.lineSeparator()));
                    HashMap<String, String> result = mapper.readValue(json, HashMap.class);
                    HashMap<String, String[]> r = new HashMap<>();

                    for (String key : result.keySet()) {
                        String[] val = new String[1];
                        val[0] = result.get(key);
                        r.put(key, val);
                    }
                    String[] val = new String[1];
                    val[0] = httpRequest.getMethod();
                    r.put("_method", val);
                    HttpServletRequest s = new MyServletRequestWrapper(httpRequest, r);
                    chain.doFilter(s, response);
                }

            }
        }
        chain.doFilter(request, response);

    }

    @Override
    public void destroy() {
    }

    class MyServletRequestWrapper extends HttpServletRequestWrapper {
        private final HashMap<String, String[]> params;

        MyServletRequestWrapper(HttpServletRequest request, HashMap<String, String[]> params) {
            super(request);
            this.params = params;
        }

        @Override
        public String getParameter(String name) {
            if (this.params.containsKey(name)) {
                return this.params.get(name)[0];
            }
            return "";
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            return this.params;
        }

        @Override
        public Enumeration<String> getParameterNames() {
            return new Enumerator<>(params.keySet());
        }

        @Override
        public String[] getParameterValues(String name) {
            return params.get(name);
        }
    }
}
1  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.jdbc.datasource.DataSourceUtils | Returning JDBC Connection to DataSource
2  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor | Found 'Content-Type:application/json;charset=UTF-8' in response
3  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor | Writing [eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiYXV0aG9yaXphdGlvbiIsIm1hZGVkaWFuZmVpIl0sInVzZXJfbmFtZSI6ImFjZHh4eDE3NyIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSIsImFsbCJdLCJleHAiOjE1ODE2ODYxODcsImF1dGhvcml0aWVzIjpbIlJPTEVf5pmu6YCa5Lq6Il0sImp0aSI6ImFjYjVhNTQ0LTQzMWMtNDlkNC04N2QyLWNkMDYxOGVlMDRhNyIsImNsaWVudF9pZCI6Im1hZGVkaWFuZmVpIn0.g3-ThU6s1CHpWH9FSp5pmxLdeRohL9N_yYcT072iUypggOguul702lXmtmqABZyNkYhzfterl2UZ4fDG40i8KJk79ivFJ5c_Rx5nMpA7ubJrnz0wgLcrg8mg8PCkXNKFGgB6S8CQiYPglQXoxFlHm767iOp0pJkSpn-jV4pvKLPHIRHgWaRysA2PdmikSZz8WaXrCVLBnzf2YyGd0h3xS2Nk-uWMJBHS-TH1lfOfkJWU7KeePEdsdvNMiBTwNAJ--9NC-WyNlrGub7B2OFaAXNc7wMhxvozpUAH_qoccasrg2aLhX3P-Gs2usQCifdlSI687b_T8ZaykMqGGJQrUgg]
4  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.security.web.header.writers.HstsHeaderWriter | Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@30bb94e4
5  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.DispatcherServlet | Completed 200 OK
6  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.security.web.access.ExceptionTranslationFilter | Chain processed normally
7  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.security.web.context.SecurityContextPersistenceFilter | SecurityContextHolder now cleared, as request processing completed
8  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.DispatcherServlet | POST "/oauth/token", parameters={}
9  >>| DEBUG | http-nio-8050-exec-1 | org.springframework.security.oauth2.provider.endpoint.FrameworkEndpointHandlerMapping | Mapped to public org.springframework.http.ResponseEntity org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(java.security.Principal,java.util.Map) throws org.springframework.web.HttpRequestMethodNotSupportedException
10 >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver | Using @ExceptionHandler public org.springframework.http.ResponseEntity org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.handleException(java.lang.Exception) throws java.lang.Exception
11 >>| WARN  | http-nio-8050-exec-1 | org.springframework.security.oauth2.provider.endpoint.TokenEndpoint | Handling error: InsufficientAuthenticationException, There is no client authentication. Try adding an appropriate authentication filter.
12 >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor | Found 'Content-Type:application/json;charset=UTF-8' in response
13 >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor | Writing [error="unauthorized", error_description="There is no client authentication. Try adding an appropriate authentication filter."]
14 >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver | Resolved [org.springframework.security.authentication.InsufficientAuthenticationException: There is no client authentication. Try adding an appropriate authentication filter.]
15 >>| DEBUG | http-nio-8050-exec-1 | org.springframework.web.servlet.DispatcherServlet | Completed 200 OK

以上是日志,照理来说应该在第7行已经结束了,为什么又来一个请求,导致TokenEndpoint.postAccessToken()又执行了一边,但是这次的Principal没有值,导致unauthorized错误,并且显示到前端

加载中
1
a
acdxxx188

终于找到原因了,原来忘记在 chain.doFilter(s, response); 后面加一个return,导致执行完后拿原来的 request 又请求了一遍,汗

返回顶部
顶部