【发布时间】:2020-10-17 20:55:40
【问题描述】:
我正在使用 Spring 安全性 + Spring 核心并与 CXF 相结合,让我安心。
以下是配置:
-
用于 CXF 配置的 web.xml:
<!-- Spring configuration for ContextLoaderListener --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- CXF configuration for resful webservices --> <servlet> <servlet-name>CXFServlet</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>CXFServlet</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> -
配置 CXF 端点 (context.xml)
<!-- configure for restful endpoint for application services as web authentication... --> <jaxrs:server id="ApplicationServices" address="/Application"> <jaxrs:serviceBeans> <ref bean="ControllerImpl" /> </jaxrs:serviceBeans> <jaxrs:providers> <ref bean="jsonProvider" /> </jaxrs:providers> <jaxrs:features> <bean id="loggingFeature" class="org.apache.cxf.feature.LoggingFeature"> <property name="prettyLogging" value="true" /> </bean> <ref bean="swagger2Feature" /> </jaxrs:features> </jaxrs:server> -
spring 安全配置 - 过滤器
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter { AuthenticationFilter(final RequestMatcher requiresAuth) { super(requiresAuth); } @Override public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException { //Optional<String> tokenParam = Optional.ofNullable(httpServletRequest.getHeader(AUTHORIZATION)); //Authorization: Bearer TOKEN String token= StringUtils.isNotEmpty(httpServletRequest.getHeader(AUTHORIZATION))? httpServletRequest.getHeader(AUTHORIZATION) : ""; token= StringUtils.removeStart(token, "Bearer").trim(); Authentication requestAuthentication = new UsernamePasswordAuthenticationToken(token, token); return getAuthenticationManager().authenticate(requestAuthentication); } @Override protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain, final Authentication authResult) throws IOException, ServletException { SecurityContextHolder.getContext().setAuthentication(authResult); chain.doFilter(request, response); } } -
spring 安全配置 - 提供者
@Component public class AuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { @Autowired UserTokenService userTokenService; @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException { // } @Override protected UserDetails retrieveUser(String userName, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken) throws AuthenticationException { Object token= usernamePasswordAuthenticationToken.getCredentials(); return Optional .ofNullable(token) .map(String::valueOf) .flatMap(userTokenService::findByToken) .orElseThrow(() -> new UsernameNotFoundException("Cannot find user with authentication token=" + token)); } } -
spring 安全配置 - SecurityConfiguration
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher( new AntPathRequestMatcher("/services/**")); AuthenticationProvider provider; public SecurityConfiguration(final AuthenticationProvider authenticationProvider) { super(); this.provider = authenticationProvider; } @Override protected void configure(final AuthenticationManagerBuilder auth) { auth.authenticationProvider(provider); } /** * we don't need provide this service for now because we are using Vaadin */ @Override public void configure(final WebSecurity webSecurity) { webSecurity.ignoring().antMatchers("/token/**"); } @Override public void configure(HttpSecurity http) throws Exception { http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().exceptionHandling().and() .authenticationProvider(provider) .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class).authorizeRequests() .requestMatchers(PROTECTED_URLS).authenticated().and().csrf().disable().formLogin().disable() .httpBasic().disable().logout().disable(); } @Bean AuthenticationFilter authenticationFilter() throws Exception { final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS); filter.setAuthenticationManager(authenticationManager()); // filter.setAuthenticationSuccessHandler(successHandler()); return filter; } @Bean AuthenticationEntryPoint forbiddenEntryPoint() { return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN); } } -
findByToken
@Override public Optional<User> findByToken(String token) { UserToken userToken = userTokenDAO.findByToken(token); if (userToken != null) { User user = new User(userToken.getUserId(), userToken.getUserPassword(), true, true, true, true, AuthorityUtils.createAuthorityList("USER")); return Optional.of(user); } return Optional.empty(); }
但是过滤器不起作用。该请求仍然允许在没有任何 Spring Security 验证的情况下进行。
请求如下:
curl -X POST "http://localhost:8080/my-app/services/Application/ControllerImpl/myservice1" -H "accept: application/json" -H "Content-Type: application/json" -d "string"
没有异常或错误。上述请求返回 200(OK)。由于请求中没有不记名令牌,我预计会失败。
我们如何将 Spring 安全性(使用不记名令牌方法)和 CXF 结合起来?
【问题讨论】:
-
是的,尝试添加:
new AntPathRequestMatcher("/my-app/services/**"),但仍然返回 200 - OK。 -
执行从未在
AntPathRequestMatcher类中命中String url = getRequestPath(request);。我担心所有带有 /services/** 的请求都将由 CXF 控制。 Spring Security 无法拦截到这个 URL 模式
标签: spring-security cxf