我有Spring Boot应用程序,一切正常,直到我在应用程序面前实现spring security。这是一个RESTful api,具有基于令牌的身份验证。什么更奇怪它工作(!)断断续续 - 间歇地我的意思是重新启动应用程序将返回正确的响应,如401/403,如果未经身份验证和其他代码,如果用户有权访问它们。这正在部署到WebLogic中。
2017-01-05 14:12:51.164 WARN 11252 --- [ (self-tuning)'] o.s.web.servlet.PageNotFound : No mapping found for HTTP request with URI [/user] in DispatcherServlet with name 'dispatcherServlet'
WebApplication.java
@SpringBootApplication(exclude = { SecurityAutoConfiguration.class })
public class WebApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) {
Object[] sources = new Object[2];
sources[0] = WebConfiguration.class;
sources[1] = WebSecurityConfiguration.class;
SpringApplication.run(sources, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(WebApplication.class);
}
}
WebConfiguration.java
@Configuration
@ComponentScan(basePackages = { "com.controller", "com.service", "com.dao"})
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class })
public class WebConfiguration extends WebMvcConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(WebConfiguration.class);
/**
* Setup a simple strategy: use all the defaults and return XML by default
* when not sure.
*/
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON).mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML);
}
@Bean(name = "entityManagerFactory")
public EntityManagerFactory getQmsEntityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setPersistenceUnitName(Config.PERSISTENCE_UNIT_NAME);
em.setPersistenceXmlLocation("META-INF/persistence.xml");
em.setDataSource(getDataSource());
em.setJpaVendorAdapter(getJpaHibernateVendorAdapter());
em.afterPropertiesSet();
return em.getObject();
}
@Bean
public HibernateJpaVendorAdapter getJpaHibernateVendorAdapter() {
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setShowSql(true);
// adapter.setDatabase("ORACLE");
adapter.setDatabasePlatform("org.hibernate.dialect.Oracle10gDialect");
return adapter;
}
@Bean(name="dataSource", destroyMethod = "")
//http://stackoverflow.com/questions/19158837/weblogic-datasource-disappears-from-jndi-tree
@Qualifier("dataSource")
@Profile("weblogic")
public DataSource dataSource() {
DataSource dataSource = null;
JndiTemplate jndi = new JndiTemplate();
try {
dataSource = (DataSource) jndi.lookup("jdbc/datasource");
} catch (NamingException e) {
logger.error("NamingException for jdbc/datasource", e);
}
return dataSource;
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
}
};
}
}
WebSecurityConfiguration.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan({
"com.subject",
"com.custom"
})
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private StatelessAuthenticationFilter statelessAuthenticationFilter;
@Autowired
private RestAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private CusAuthenticationProvider cusAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(cusAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.securityContext()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.addFilterBefore(statelessAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler);
}
}
StatelessAuthenticationFilter.java
@Component
public class StatelessAuthenticationFilter extends OncePerRequestFilter {
@Inject
private SubjectLookupService subjectLookupService;
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(authenticateUser(request));
filterChain.doFilter(request, response);
}
private Authentication authenticateUser(HttpServletRequest request) {
try {
String application = StringUtils.defaultString(request.getParameter("application"));
UserInfo me = subjectLookupService.getUserInfo();
List<GrantedAuthority> roles = me.getRoles().stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName())).collect(Collectors.toList());
UserDetails user = new User(me.getUsername(), "", roles);
Authentication authentication = new UserAuthentication(user);
return authentication;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Controller.java
@RestController
public class Controller {
@Autowired
private QService qService;
@PreAuthorize("hasAnyRole('view', 'admin')")
@RequestMapping(value = "/q/{year}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public ResponseEntity<?> listQuotas(@PathVariable Integer year) {
return new ResponseEntity<>(qService.listQs(year), HttpStatus.OK);
}
@RequestMapping(value = "/user", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public ResponseEntity<?> user(HttpServletRequest request) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return new ResponseEntity<>( auth.getPrincipal(), HttpStatus.OK);
}
@PreAuthorize("hasRole('shouldntauthorize')")
@RequestMapping(value = "/unauthorized/{year}", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public ResponseEntity<?> unauthorized(@PathVariable Integer year) {
return new ResponseEntity<>(qService.listQs(year), HttpStatus.OK);
}
}
当它工作时 - 我能够使用HTTP获取点击任何上述方法,我得到正确的响应。如果它不能正常工作,我会不断得到:
2017-01-05 14:18:47.506 WARN 11252 --- [ (self-tuning)'] o.s.web.servlet.PageNotFound : No mapping found for HTTP request with URI [/user] in DispatcherServlet with name 'dispatcherServlet'
我可以在日志中验证Spring Boot初始化时应用程序也设置了正确的映射URL。
任何想法可能会出现问题吗?
答案 0 :(得分:0)
当你说&#34;间歇地&#34;我倾向于认为问题出在Spring启动配置上。
所以,我已经厌倦了你有两次@ComponentScan
和不同包裹的事实。
您可以尝试删除
@ComponentScan(basePackages = { "com.controller", "com.service", "com.dao"})
@ComponentScan({ "com.subject", "com.custom" })
从类WebSecurityConfiguration.java ,并用一个
替换它们@ComponentScan(basePackages = { "com.controller", "com.service", "com.dao", "com.subject", "com.custom"})
主要的SpringBoot类中的?