簡體   English   中英

Spring Security-自動接線不起作用

[英]Spring Security - Autowired not working

這是我正在研究的實踐項目,旨在學習Spring Security和OAuth2。

鏈接到項目的zip- https://drive.google.com/open?id=0BxsYBg5XwboXdkpUdkhXWUd1Vmc

一旦添加以下類,我的自動裝配服務就會失敗:(它給出NullPointerException。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

我在其余的控制器下面得到了NullPointerException userService

@RestController
@RequestMapping("/api/user")
public class UserCtrl {

@Autowired
@Qualifier("userService")
UserService userService;

@PreAuthorize("#oauth2.hasScope('write')")
@RequestMapping(method=RequestMethod.POST,consumes="application/json")
private @ResponseBody ResponseMessage registerUser(@RequestBody User user){
    user.setUser_id(-1);
    return userService.createUser(user);
}

@PreAuthorize("#oauth2.hasScope('none')")
@RequestMapping(method=RequestMethod.GET)
private @ResponseBody ResponseMessage loginUser(){

    CustomUserDetails temp =  (CustomUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    System.out.println(temp.getUsername() + " logged in");

    ResponseMessage message = userService.getUserByUsername(temp.getUsername());

    if(message.getCode() == ResponseMessage.CODE_NOT_FOUND){
        return message;
    }else{
        temp.setUser((User)message.getData());
    }

    return userService.loginUser(temp.getUser().getUsername(),temp.getUser().getPassword());
}

@PreAuthorize("hasRole('ROLE_USER')")
@RequestMapping(method=RequestMethod.PUT,consumes="application/json")
private @ResponseBody ResponseMessage updateUser(@RequestBody User user){
    return userService.updateUser(user);
}

@PreAuthorize("hasRole('ROLE_USER')")
@RequestMapping(method=RequestMethod.DELETE,consumes="application/json")
private @ResponseBody ResponseMessage deleteUser(@RequestBody User user){
    return userService.deleteUser(user.getUser_id());
}
}

這是我定義服務的方式:

@Service("userService")
public class UserServiceImpl implements UserService {

@Autowired
private UserDAO userDAO;

@Autowired
private RoleService roleService;

public UserServiceImpl() {
    System.out.println("service");
}

@Override
@Transactional
public ResponseMessage createUser(User user) {
    if (null == userDAO.getUserByUsername(user.getUsername())) {
        int id = userDAO.createUser(user);
        user.setUser_id(id);
        roleService.createRole(new Role(RoleType.ROLE_USER, user));

        return new ResponseMessage(ResponseMessage.CODE_CREATED, ResponseMessage.DESC_CREATED, user);
    } else {
        return new ResponseMessage(ResponseMessage.CODE_EXISTS, ResponseMessage.DESC_EXISTS, user);
    }
}

Mvc配置:

@EnableWebMvc
@Configuration
@ComponentScan({"com.rawal.sweetnote.*"})
public class WebMvcConfig extends WebMvcConfigurerAdapter{

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}
}

春季安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

@Autowired
@Qualifier("userService")
UserService userDetailsService;

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService);
}   
}

安全初始化器:

@Order(1)
public class SpringSecurityInitializer extends  AbstractSecurityWebApplicationInitializer{

}

DispatcherServletInitializer

public class AppInit extends AbstractAnnotationConfigDispatcherServletInitializer{

@Override
protected Class<?>[] getRootConfigClasses() {
    // TODO Auto-generated method stub
    return new Class[]{MethodSecurityConfig.class,WebMvcConfig.class};
}

@Override
protected Class<?>[] getServletConfigClasses() {
    // TODO Auto-generated method stub
    return null;
}

@Override
protected String[] getServletMappings() {
    // TODO Auto-generated method stub
    return new String[]{"/"};
}
}

休眠配置:

@Configuration
@EnableTransactionManagement
@PropertySource(value = { "classpath:app.properties" })
public class HibernateConfig {
/**
 * This field is automatically injected by the spring framework from app.properties
 */
@Autowired
private Environment environment;



/**
 * Creates a session factory
 * @return {@link SessionFactory}
 */
@Bean
public LocalSessionFactoryBean sessionFactory() {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] { "com.rawal.sweetnote.entities" });
    sessionFactory.setHibernateProperties(hibernateProperties());
    return sessionFactory;
}


/**
 * Creates a datasource after setting various database properties
 * @return {@link DataSource}
 */
@Bean
public DataSource dataSource() {
    DriverManagerDataSource dataSource = new DriverManagerDataSource();
    dataSource.setDriverClassName(environment.getRequiredProperty("db.drivername"));
    dataSource.setUrl(environment.getRequiredProperty("db.url"));
    dataSource.setUsername(environment.getRequiredProperty("db.username"));
    dataSource.setPassword(environment.getRequiredProperty("db.password"));
    return dataSource;
}


/**
 * Sets up the hibernate properties and returns an instance of it
 * @return {@link Properties}
 */
private Properties hibernateProperties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect", environment.getRequiredProperty("hibernate.dialect"));
    properties.put("hibernate.show_sql", environment.getRequiredProperty("hibernate.show_sql"));
    return properties;
}



/**
 * Creates a transaction manager using the sessionfactory injected by spring and returns an instance of it
 * @param {@link SessionFactory}
 * @return {@link HibernateTransactionManager}
 */
@Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
    HibernateTransactionManager txManager = new HibernateTransactionManager();
    txManager.setSessionFactory(s);
    return txManager;
}


/**
 * Creates a hibernate template instance from the injected session factory.
 * We use this to perform various db transactions.
 * @param {@link SessionFactory}
 * @return
 */
@Bean
@Autowired
public HibernateTemplate hibernateTemplate(SessionFactory sessionFactory) {
    HibernateTemplate hibernateTemplate = new HibernateTemplate();
    hibernateTemplate.setSessionFactory(sessionFactory);
    return hibernateTemplate;
}
}

OAuth2資源配置

@Configuration
@EnableResourceServer
public class OAuthResourceConfig extends ResourceServerConfigurerAdapter{

private static final String RESOURCE_ID = "restservice";

@Override
public void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/api/**").authenticated()
    .antMatchers("/register").permitAll()
    .and().formLogin().permitAll()
    .and().logout().permitAll()
    .and().csrf().disable();
}

@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    resources.resourceId(RESOURCE_ID).stateless(false);
}
}

OAuth2服務器配置

@Configuration
@EnableAuthorizationServer
@PropertySource("classpath:app.properties")
public class OAuthServerConfig extends AuthorizationServerConfigurerAdapter{

@Autowired
private Environment env;


@Autowired
private UserService userDetailsService;

@Autowired
private AuthenticationManager authenticationManager;

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints.tokenStore(tokenStore()).tokenEnhancer(tokenEnhancer()).authenticationManager(authenticationManager).userDetailsService(userDetailsService);
}

@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.allowFormAuthenticationForClients();
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory().withClient("client")
    .authorizedGrantTypes("password","refresh_token","implicit")
    .scopes("read","write","trust")
    .refreshTokenValiditySeconds(Integer.parseInt(env.getProperty("refresh_token_validity")))
    .accessTokenValiditySeconds(Integer.parseInt(env.getProperty("access_token_validity")));
}

@Bean
public TokenStore tokenStore() {
    InMemoryTokenStore store = new InMemoryTokenStore();
    store.setAuthenticationKeyGenerator(new UniqueAuthenticationKeyGenerator());
    return store;
}

@Bean
public TokenEnhancer tokenEnhancer() {
    return new CustomTokenEnhancer();
}
}

Stacktrace的異常:

java.lang.NullPointerException
com.rawal.sweetnote.controllers.UserCtrl.loginUser(UserCtrl.java:40)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:177)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:121)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)

更新1

如下修改了用戶控制器(添加了greet1()和greet2())。 現在有趣的是,這些新方法的UserService屬性不為null。 但是對於其他方法,它仍然為空。

@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping("/greet")
public String greet() {
    System.out.println(service.sayHello());
    return "Hello";
}

@PreAuthorize("hasRole('ROLE_USER')")
@RequestMapping("/greet2")
public String greet2() {
    System.out.println(service.sayHello());
    return "Hello";
}


@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(method=RequestMethod.POST,consumes="application/json")
private @ResponseBody ResponseMessage registerUser(@RequestBody User user){
    user.setUser_id(-1);
    return service.createUser(user);
}

@PreAuthorize("hasRole('ROLE_USER')")
@RequestMapping(path="/",method=RequestMethod.GET)
private @ResponseBody ResponseMessage loginUser(){

    CustomUserDetails temp =  (CustomUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    System.out.println(temp.getUsername() + " logged in");


    service.sayHello();
    ResponseMessage message = service.getUserByUsername(temp.getUsername());

    if(message.getCode() == ResponseMessage.CODE_NOT_FOUND){
        return message;
    }else{
        temp.setUser((User)message.getData());
    }

    return service.loginUser(temp.getUser().getUsername(),temp.getUser().getPassword());
}

但是,如果禁用prePostEnabled,則一切正常。 這感覺真是愚蠢! 救命!!!!!

好的,這真的是“ ME”的愚蠢之處。 我只是注意到控制器中的所有方法都是私有的。 :(讓他們公開解決了這個問題。

然而!!!!! 我仍然想知道@EnableGlobalMethodSecurity(prePostEnabled = true)設置為false

如果您得到這個請發表評論。

希望這可以幫助像我這樣愚蠢的人。 :/

確保您的public控制器不是private

@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(method=RequestMethod.POST,consumes="application/json")
public ResponseMessage registerUser(@RequestBody User user){
   // your code here
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM