当我使用 servletRequest.getReader().lines().collect(Collectors.joining()) 时请求更改正文

Posted

技术标签:

【中文标题】当我使用 servletRequest.getReader().lines().collect(Collectors.joining()) 时请求更改正文【英文标题】:Request body change when I Use servletRequest.getReader().lines().collect(Collectors.joining()) 【发布时间】:2022-01-16 02:35:49 【问题描述】:

我在java、jwt、spring security中做一个私有api,第一次进来请求一个json对象。

user: xxx
password: yyy

API 在正文中返回一个jwt token

其他人称令牌进入正文 json 并验证它我使用这个:

sbody = servletRequest.getReader().lines().collect(Collectors.joining());

要获取字段令牌并正常,但随后过滤器会显示消息:

"Required request body is missing: public org.springframework.http.ResponseEntity"

这是我的 api:

@SpringBootApplication
public class JwtApplication 

    public static void main(String[] args) 
        SpringApplication.run(JwtApplication.class, args);
    

    @EnableWebSecurity
    @Configuration
    class WebSecurityConfig extends WebSecurityConfigurerAdapter 

        @Override
        protected void configure(HttpSecurity http) throws Exception 
            http.csrf().disable()
                    .addFilterAfter(new JWTAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class)
                    .authorizeRequests().antMatchers(HttpMethod.POST, "/user").permitAll()
                    .antMatchers(HttpMethod.POST, "/Autenticacion").permitAll().anyRequest().authenticated();
        

    

这是过滤器:

public class JWTAuthorizationFilter extends OncePerRequestFilter 

    private final String HEADER = "Authorization";
    private final String SESSION = "sesion";
    private final String PREFIX = "Bearer ";
    private final String SECRET = "mySecretKey";
    public static final long EXPIRATION_TIME = 900_000; // 15 mins

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException 
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        try 
            boolean resultado_checktoken = checkJWTToken(httpRequest, httpResponse);
            if (resultado_checktoken) 
                Claims claims = validateToken(request);
                if (claims.get("authorities") != null) 
                    setUpSpringAuthentication(claims);
                 else 
                    SecurityContextHolder.clearContext();
                
             else 
                SecurityContextHolder.clearContext();
            
            chain.doFilter(request, response);
         catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException e) 
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            ((HttpServletResponse) response).sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
            return;
        
         System.out.println("supuestamente no hubo problemas");
    

    private Claims validateToken(HttpServletRequest request) 
        //String jwtToken = request.getHeader(HEADER).replace(PREFIX, "");
        String jwtToken="";
        try 
            jwtToken = this.getBodySession(request);
         catch (IOException e) 
            e.printStackTrace();
        ;
        return Jwts.parser().setSigningKey(SECRET.getBytes()).parseClaimsJws(jwtToken).getBody();
    
    
    /**
     * Authentication method in Spring flow
     * 
     * @param claims
     */
    private void setUpSpringAuthentication(Claims claims) 
        @SuppressWarnings("unchecked")
        List<String> authorities = (List<String>) claims.get("authorities");
        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(claims.getSubject(), null,
                authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
        SecurityContextHolder.getContext().setAuthentication(auth);
    

    private boolean checkJWTToken(HttpServletRequest request, HttpServletResponse res) throws IOException 
        String authenticationHeader = "";
        authenticationHeader = this.getBodySession(request);
        if (authenticationHeader == null || !authenticationHeader.startsWith(PREFIX))
            return false;
        return true;
    

    public String getBodySession(HttpServletRequest request) throws IOException 
        String sbody = "";
        HttpServletRequest servletRequest = new ContentCachingRequestWrapper(request);
        //servletRequest.getParameterMap();
        sbody = servletRequest.getReader().lines().collect(Collectors.joining());
        String Field = SESSION;
        String scampo = "";
        if (sbody.contains(Field)) 
            scampo = sbody.substring(sbody.indexOf(Field), sbody.indexOf("\n", sbody.indexOf(Field)))
                    .replace(Field + "\": \"", "").replace("\"", "").replace(",", "");
        
        System.out.println("sbody: " + sbody + " sesion: " + scampo);
        return scampo;
    

【问题讨论】:

所有这些都是自定义安全性,这是不好的做法。当所有这些都已经存在于 Spring Security 中时,为什么要编写自定义 jwtfilter。 jwtfilter 中已经有一个可以自定义的构建。删除整个过滤器并阅读 spring 安全文档中关于 jwts 的章节。投反对票。 谢谢,我是 Spring Boot 新手,但我也需要生成安全令牌,而且我正在使用 JWT。 如果你是新手,那么你应该阅读官方的 spring 安全文档章节,了解如何实现 jwts 的处理,然后再发布堆栈溢出。 【参考方案1】:

这需要明确地返回一个布尔值,你不能有两个返回语句。

private boolean checkJWTToken(HttpServletRequest request, HttpServletResponse res) throws IOException 
        String authenticationHeader = "";
        authenticationHeader = this.getBodySession(request);
        if (authenticationHeader == null || !authenticationHeader.startsWith(PREFIX))
            **return false;**
        **return true;**
    

【讨论】:

谢谢,我解决了

以上是关于当我使用 servletRequest.getReader().lines().collect(Collectors.joining()) 时请求更改正文的主要内容,如果未能解决你的问题,请参考以下文章

为啥在我的 c 程序中,当我使用 double 时它只输出 0,但是当我使用 float 时它可以工作? [复制]

当我访问我的 iframe 时,当我使用 selenium 时,#document 不显示

当我在 ngOnInit() 中使用 router.getCurrentNavigation() 时,它会给我类型错误,但是当我在构造函数中使用它时,它工作正常,为啥?

当我不知道 data.frame 中的列名时,当我使用 dplyr mutate 函数时

Cordova/Phonegap - 当我关闭应用程序时存储一个数组(当我重新打开时使用它们)

为啥当我解构属性时接收道具的组件不起作用,但是当我使用 props.key 时它起作用了?