【问题标题】:spring boot security authentication to verify body contentsspring boot 安全认证验证正文内容
【发布时间】:2021-01-12 16:06:33
【问题描述】:

我想验证一个发布请求正文键值对,但我想在拦截器/过滤器的帮助下做同样的事情。我该怎么做?

【问题讨论】:

标签: java spring spring-boot spring-security spring-security-rest


【解决方案1】:

您可以创建一个自定义请求过滤器来检查请求:

public class MyFilter implements OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
        var user = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        // do stuff you need to do here
        
        filterChain.doFilter(request, response);
    }
}

然后在您的 WebSecurityConfiguration 类中像这样注册过滤器

public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterAfter(new MyFilter(), BasicAuthenticationFilter.class);
    }
}

【讨论】:

  • SecurityContextHolder.getContext().getAuthentication().getPrincipal() 返回 null,如果我这样做,有什么想法吗?
【解决方案2】:

您可以扩展 HandlerInterceptorAdapter 并通过覆盖 preHandle() 方法在请求之上执行您的自定义操作/过滤器。

伪代码在这里:

@Component
public class SimpleInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // Handle your request here. In your case, authentication check should go here.
        return true;
    }
}

SimpleInterceptor 添加到注册表以拦截请求。

@Configuration
@EnableWebMvc
public class SimpleMvnConfigurer implements WebMvcConfigurer {

    @Autowired
    SimpleInterceptor simpleInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(simpleInterceptor);
    }
}

就是这样!
编辑1: 要从preHandle 方法发送响应,请遵循以下伪代码:

@Override                                                                                           
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    // Handle your request here. AIn your case, authentication check should go here.                
    if (!isValidAuth()) {                                                                           
        // Populate the response here.                                                              
        try {                                                                                       
            response.setStatus(401);                                                                
            response.getWriter().write("Authentication failed.");                                   
        } catch (IOException e) {                                                                   
            e.printStackTrace();                                                                    
        }                                                                                           
        return false;                                                                               
    }                                                                                               
    return true;                                                                                    
}                                                                                                   ```

【讨论】:

  • 如果我在 preHandle 中进行的身份验证失败,我该如何发送 401 Http 错误响应?
  • 更新了响应。请检查。
  • 问题是我无法读取其中的请求正文。由于我需要检查请求正文中的参数之一,请参阅此链接 ..stackoverflow.com/questions/21193380/….
  • 您的身份验证是如何发送的?在请求正文中?我希望,通常身份验证令牌是通过标头发送的。
  • 是的,我可以通过它访问经过身份验证的用户。 String user=SecurityContextHolder.getContext().getAuthentication().getName(),但我需要用这个用户验证帖子正文参数之一。
【解决方案3】:

你可以用过滤器试试这个。

public class SimpleFilter implements Filter {

    private void throwUnauthorized(ServletResponse res) throws IOException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.reset();
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;

        if (!isValidAuth(request)) {
            throwUnauthorized(res);
        }
        chain.doFilter(req, res);

    }

    private boolean isValidAuth(HttpServletRequest request) {
        // YOUR LOGIC GOES HERE.
        return false;
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig arg0) {
    }

}

使用 FilterRegistrationBean 注册过滤器

@Bean                                                                                      
public FilterRegistrationBean<SimpleFilter> simpleFilter() {                               
    FilterRegistrationBean<SimpleFilter> registrationBean = new FilterRegistrationBean<>();
    registrationBean.setFilter(new SimpleFilter());                                        
                                                                                           
    return registrationBean;                                                               
}                                                                                          

让我知道这是否有效。

【讨论】:

  • 我的类在有问题的编辑中扩展了 OncePerRequestFilter,我已经覆盖了 doFilterInternal 方法。有没有关系,我的意思是它与实现过滤器类不同吗?
  • 问题是我无法在调用 do filter 之前提取请求正文,我收到错误:响应已提交
猜你喜欢
  • 2018-09-07
  • 2021-01-17
  • 1970-01-01
  • 2018-05-19
  • 1970-01-01
  • 2018-12-10
  • 2020-10-18
  • 2015-03-21
  • 2019-02-21
相关资源
最近更新 更多