gpt4 book ai didi

java - 我如何告诉 spring security 只为特定端口应用 authorizeRequests?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:48:38 30 4
gpt4 key购买 nike

We configured our new micro service (using Spring-Boot) in a way that the official API is on port 8080 (which is be mapped outside of our virtual network to normal HTTPS on port 443), while some management functions are on a secondary HTTP port 7979. These are only used inside the virtual network, and used for monitoring, loadbalancing etc.

All API access needs to be secured with OAuth, while the management functions should be accessible freely inside the network. So we configured Spring security this way (http is a HttpSecurity object):

    http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests()
.antMatchers("/info").anonymous()
.antMatchers("/health").anonymous()

.antMatchers(HttpMethod.GET, "/warehouses/**").access(oauthScopeRead)
.antMatchers(HttpMethod.PUT, "/warehouses/**").access(oauthScopeWrite)

.anyRequest().denyAll();

This has the effect on both ports: /info and /health are unauthorized, while /warehouses needs authentication, and everything else also needs authentication (returns 401, but when invoking with authentication, it returns 403).

As there is no /info or /health on the public port, these return 404 for unauthorized users, while everything else returns 401. I'm unsatisfied with this and would like to have

  • on the public port, require authentication for everything (and return 404 or 403 only after being authenticated)
  • on the admin port, require no authentication at all (return 404 for everything which is not one of the configured endpoints).

I couldn't find anything about ports in the Spring Security Javadocs or reference documentation .

What can I do here?

最佳答案

我找到了一个解决方案:

authorizeRequests()这里的方法返回一个 ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry ,它有(来自它的祖先类 AbstractRequestMatcherRegistry)旁边的一些 antMatchers方法也是一个通用的 requestMatchers()方法,需要一个或多个 RequestMatcher对象。原来这是一个我可以自己实现的接口(interface):

/**
* A request matcher which matches just a port.
*
* @param port the port to match.
*
* @return the new matcher.
*/
private RequestMatcher forPort(final int port) {
return (HttpServletRequest request) -> port == request.getLocalPort();
}

(这是 Java 8 语法,对于以前的 Java 版本,您必须在此处编写一个匿名类。)

同时 requestMatchers需要几个这样的匹配器,看起来它们是由 OR 连接的(至少 this example suggests 这个),因此我使用 AndRequestMatcher 将它连接到路径(和 HTTP 方法)的匹配器。

最终代码如下所示:

@Value("${management.port}")
private int managementPort;

@Value("${server.port}")
private int apiPort;

/**
* Configure scopes for specific controller/httpmethods/roles here.
*/
@Override
public void configure(final HttpSecurity http) throws Exception {
//J-
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and()
.authorizeRequests()
.requestMatchers(forPortAndPath(managementPort, "/info")).anonymous()
.requestMatchers(forPortAndPath(managementPort, "/health")).anonymous()

.requestMatchers(forPortAndPath(apiPort, HttpMethod.GET, "/warehouses/**")).access(oauthScopeRead)
.requestMatchers(forPortAndPath(apiPort, HttpMethod.PUT, "/warehouses/**")).access(oauthScopeWrite)

.anyRequest().denyAll();
//J+
}

/**
* Creates a request matcher which only matches requests for a specific local port and path (using an
* {@link AntPathRequestMatcher} for the path part).
*
* @param port the port to match
* @param pathPattern the pattern for the path.
*
* @return the new request matcher.
*/
private RequestMatcher forPortAndPath(final int port, @Nonnull final String pathPattern) {
return new AndRequestMatcher(forPort(port), new AntPathRequestMatcher(pathPattern));
}

/**
* Creates a request matcher which only matches requests for a specific local port, path and request method (using
* an {@link AntPathRequestMatcher} for the path part).
*
* @param port the port to match
* @param pathPattern the pattern for the path.
* @param method the HttpMethod to match. Requests for other methods will not be matched.
*
* @return the new request matcher.
*/
private RequestMatcher forPortAndPath(final int port, @Nonnull final HttpMethod method,
@Nonnull final String pathPattern) {
return new AndRequestMatcher(forPort(port), new AntPathRequestMatcher(pathPattern, method.name()));
}

/**
* A request matcher which matches just a port.
*
* @param port the port to match.
*
* @return the new matcher.
*/
private RequestMatcher forPort(final int port) {
return (HttpServletRequest request) -> { return port == request.getLocalPort(); };
}

这并没有完全反射(reflect)出问题:managementPort 在这里只有“/info”和“/health”公共(public)可达,而不是所有内容。

你可以用这个

                 .requestMatchers(forPort(managementPort)).anonymous()

使此端口完全未授权。

关于java - 我如何告诉 spring security 只为特定端口应用 authorizeRequests?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35755716/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com