Paŭ*_*ann 6 java port spring spring-security
我们以官方API在端口8080(在我们的虚拟网络之外映射到端口443上的普通HTTPS)的方式配置我们的新微服务(使用Spring-Boot),而一些管理功能在辅助HTTP上端口7979.这些只在虚拟网络中使用,用于监控,负载均衡等.
所有API访问都需要使用OAuth保护,而管理功能应该可以在网络内自由访问.所以我们以这种方式配置Spring安全性(http是一个HttpSecurity对象):
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();
Run Code Online (Sandbox Code Playgroud)
这对两个端口都有影响:/info并且/health是未经授权的,同时/warehouses需要身份验证,其他一切也需要身份验证(返回401,但是在使用身份验证调用时,它返回403).
由于没有/info或/health在公共端口,这些返回404为未经授权的用户,而其他一切返回401.我对此不满意并希望有
我在Spring Security Javadocs或参考文档中找不到任何关于端口的信息.
我能在这做什么?
Paŭ*_*ann 10
我找到了解决方案:
authorizeRequests()这里的方法返回一个ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry,它(从它的祖先类AbstractRequestMatcherRegistry)旁边的某些antMatchers方法也是一个泛型requestMatchers()方法,它接受一个或多个RequestMatcher对象.事实证明这是我可以自己实现的界面:
/**
* 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();
}
Run Code Online (Sandbox Code Playgroud)
(这是Java 8语法,对于以前的Java版本,您必须在此处编写任何匿名类.)
虽然requestMatchers需要几个这样的匹配器,看起来它们通过OR连接(至少这个例子表明这个),因此我使用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(); };
}
Run Code Online (Sandbox Code Playgroud)
这并没有完全反映这个问题:managementPort在这里只有"/ info"和"/ health"公共可达,而不是一切.
你可以用它
.requestMatchers(forPort(managementPort)).anonymous()
Run Code Online (Sandbox Code Playgroud)
使这个端口完全未经授权.
| 归档时间: |
|
| 查看次数: |
8846 次 |
| 最近记录: |