我遇到Spring REST oAuth2配置问题。 Springs查看并映射我的URL,但在oauth2安全检查(成功)声明后,没有匹配的URL。但我不明白为什么,因为Spring在app初始化时看到了它。 我能够使用/ oauth / token进行适当的身份验证并生成令牌。 我只是无法处理不需要使用令牌授权的请求。
Spring 4.0.6,spring-security 3.2.4,Spring-security-oauth2 2.0.1
来自上下文初始化的日志
2014-08-29 08:56:26.415 [Scanner-1] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users/{email}],methods=[PUT],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity> com.example.user.UserCommandsController.update(java.lang.String)
2014-08-29 08:56:26.416 [Scanner-1] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users/{email}],methods=[DELETE],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity> com.example.user.UserCommandsController.delete(java.lang.String)
2014-08-29 08:56:26.416 [Scanner-1] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users/logout],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity> com.example.user.UserCommandsController.logout()
2014-08-29 08:56:26.416 [Scanner-1] INFO o.s.w.s.m.m.a.RequestMappingHandlerMapping - Mapped "{[/api/users],methods=[POST],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.concurrent.Callable<org.springframework.http.ResponseEntity<java.lang.Void>> com.example.user.UserCommandsController.signup(java.lang.String,java.lang.String)
发送请求后
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/api/users'; against '/api/users'
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /api/users; Attributes: [permitAll]
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.a.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@31b7d21c, returned: 1
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object
2014-08-29 09:00:58.654 [qtp1157726741-28] DEBUG o.s.s.web.FilterChainProxy - /api/users reached end of additional filter chain; proceeding with original chain
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.w.servlet.DispatcherServlet - DispatcherServlet with name 'dispatcher' processing POST request for [/api/users]
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Looking up handler method for path /api/users
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping - Did not find handler method for [/api/users]
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Looking up handler method for path /api/users
2014-08-29 09:00:58.655 [qtp1157726741-28] DEBUG o.s.s.o.p.e.FrameworkEndpointHandlerMapping - Did not find handler method for [/api/users]
2014-08-29 09:00:58.655 [qtp1157726741-28] WARN o.s.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/api/users] in DispatcherServlet with name 'dispatcher'
配置
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("sample-resource-id");
}
@Override
public void configure(final HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http
.requestMatchers()
.antMatchers(HttpMethod.POST, "/api/buildings/**")
.antMatchers(HttpMethod.DELETE, "/api/**")
.antMatchers(HttpMethod.PATCH, "/api/**")
.antMatchers(HttpMethod.PUT, "/api/**")
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/buildings/**").access("hasRole('ROLE_USER')")
.antMatchers(HttpMethod.DELETE, "/api/**").access("hasRole('ROLE_USER')")
.antMatchers(HttpMethod.PATCH, "/api/**").access("hasRole('ROLE_USER')")
.antMatchers(HttpMethod.PUT, "/api/**").access("hasRole('ROLE_USER')");
}
}
@Controller
@EnableWebSecurity
@Profile("default")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
/**
* By default all request need authentication. Only those which do not need it, shall be specified explicitly.
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http
.csrf().disable();
http
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/buildings/**").permitAll()//to consider anonymous()
.antMatchers(HttpMethod.POST, "/api/users").permitAll()//to consider anonymous()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/app/**","/webjars/**", "/images/**", "/oauth/uncache_approvals", "/oauth/cache_approvals");
}
@Override
@Bean(name = "authenticationManagerBean")
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
用户控制器的一部分
@RestController
@RequestMapping("/api")
public class UserCommandsController {
private final UserService userService;
private AccountRecoveryMailer accountRecoveryMailer;
private MessageSource messageSource;
@Inject
public UserCommandsController(final UserService userService, final AccountRecoveryMailer accountRecoveryMailer,
final MessageSource messageSource) {
this.userService = userService;
this.accountRecoveryMailer = accountRecoveryMailer;
this.messageSource = messageSource;
}
@RequestMapping(value = "/users", method = RequestMethod.POST)
public Callable<ResponseEntity<Void>> signup(@RequestParam String email, @RequestParam String password) {
return () -> {
//do something
};
}
}
我想要实现的是保护所有请求,并且只有部分请求可以免费访问(或者可能只有Authorization标头来匹配client_id)。
答案 0 :(得分:0)
这是我的问题的解决方案。这个邪恶的东西的根源是bean初始化,或者更好地说它们的范围。不需要BTW SSL。
下面的配置错误,请勿盲目复制粘贴。
我有两个@ ComponentScan 类。
@Configuration
@EnableWebMvc
@ComponentScan(basePackageClasses = Application.class,
excludeFilters = @Filter({RestController.class, Controller.class, Service.class, Repository.class, Configuration.class}))
class WebMvcConfig extends WebMvcConfigurationSupport {
//some code
}
@Configuration
@ComponentScan(basePackageClasses = Application.class)
class ApplicationConfig {
//some code
}
我的WebAppInitialization代码
@Order(2)
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{ApplicationConfig.class, DataSourceConfig.class, SecurityConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{WebMvcConfig.class};
}
@Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return new Filter[]{characterEncodingFilter};
}
@Override
protected void customizeRegistration(ServletRegistration.Dynamic registration) {
registration.setInitParameter("defaultHtmlEscape", "true");
registration.setInitParameter("spring.profiles.active", "default");
}
}
如您所见,使用所有类型的bean的整个组件类路径扫描将在 getRootConfigClasses()方法中初始化,并且只有部分bean将在 getServletConfigClasses()<中初始化/ em>方法,由于 WebMvcConfig.class 而在组件扫描中排除了一些bean类型。在我看来,这个应该足够,因为来自 rootContext 的bean可用于 servletContext 。并且是,但仅适用于Web应用程序实例化。 Spring Security oAuth2没有看到控制器映射。
解决这个问题的解决方案是为了摆脱WebMvcConfig中的组件扫描,并将 getServletConfigClasses()方法更改为:
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{ApplicationConfig.class, WebMvcConfig.class};
}
感谢Spring bean的热切缓存,一切都会好起来的。
答案 1 :(得分:-1)
您使用oAuth2设置服务器,该服务器只能以安全方式访问(https :)。 如果您需要提供非安全(http :)服务,则必须创建另一台服务器。
考虑一下,如果您家的门已经锁上,只有拥有钥匙的人可以进入您家,您的房屋就是安全的。
如果您在家中添加另一扇没有锁的门,您的房屋将变得不安全。
如果您想要没有锁的门,您应该将门安装到其他小屋以便安全使用。
安全居家,非安全小屋。 这些可能是您希望在服务器上构建的内容。