没有找到带有URI的HTTP请求的映射

时间:2017-01-05 14:39:10

标签: rest spring-boot spring-security

我有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。

任何想法可能会出现问题吗?

1 个答案:

答案 0 :(得分:0)

当你说&#34;间歇地&#34;我倾向于认为问题出在Spring启动配置上。

所以,我已经厌倦了你有两次@ComponentScan和不同包裹的事实。

您可以尝试删除

@ComponentScan(basePackages = { "com.controller", "com.service", "com.dao"})
WebConfiguration.java和

@ComponentScan({ "com.subject", "com.custom" })
从类WebSecurityConfiguration.java

,并用一个

替换它们
@ComponentScan(basePackages = { "com.controller", "com.service", "com.dao", "com.subject", "com.custom"})
主要的SpringBoot类中的