将Spring Security添加到现有的Spring Web应用程序中(使用JavaConfig)

3

我有一个Spring MVC Rest Web应用程序,正在为其添加一层Spring Security。

在阅读Spring文档时,我无法理解第3.1.3节的含义。我将该部分内容复制/粘贴如下。

If we were using Spring elsewhere in our application we probably already had a WebApplicationInitializer that is loading our Spring Configuration. If we use the previous configuration we would get an error. Instead, we should register Spring Security with the existing ApplicationContext. For example, if we were using Spring MVC our SecurityWebApplicationInitializer would look something like the following:

import org.springframework.security.web.context.*;

public class SecurityWebApplicationInitializer
      extends AbstractSecurityWebApplicationInitializer {

}

This would simply only register the springSecurityFilterChain Filter for every URL in your application. After that we would ensure that SecurityConfig was loaded in our existing ApplicationInitializer. For example, if we were using Spring MVC it would be added in the getRootConfigClasses()

public class MvcWebApplicationInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { SecurityConfig.class };
    }

    // ... other overrides ...
}

那么,我已经拥有以下内容

an Initializer.java (replacement of web.xml)
Config.java - Root Context
RestServlet.java - Servlet Context

这是我的Initializer.java文件

public class Initializer implements WebApplicationInitializer {

    public void onStartup(ServletContext container) throws ServletException {

      // Create the 'root' Spring application context
      AnnotationConfigWebApplicationContext rootContext =
        new AnnotationConfigWebApplicationContext();
      rootContext.register(Config.class);

      // Manage the lifecycle of the root application context
      container.addListener(new ContextLoaderListener(rootContext));
//      container.addListener(new ContextLoaderListener(rootContext));

      // Create the dispatcher servlet's Spring application context
      AnnotationConfigWebApplicationContext dispatcherContext =
        new AnnotationConfigWebApplicationContext();
      dispatcherContext.register(RestServlet.class);

      // Register and map the dispatcher servlet
      ServletRegistration.Dynamic dispatcher =
        container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
      dispatcher.setLoadOnStartup(1);
      dispatcher.addMapping("/");


    }
 }

为了增加Spring Security层,我添加了以下内容。
SecurityConfig.java
SecurityInitializer.java

SecurityConfig.java(这是用于测试使用内存身份验证细节的文件)。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

       @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

SecurityInitializer.java

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer
              {


    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { SecurityConfig.class };
    }

现在的问题是我不确定如何执行这些步骤。我不知道(根据文档的3.2.3节)是否应该扩展AbstractSecurityWebApplicationInitializer还是AbstractAnnotationConfigDispatcherServletInitializer。
另一个问题是这是一个REST应用程序。我没有任何返回jsps的控制器(我也不想要!)。我的最终目标是使用OAuth2,在前端Web应用程序(基于Angular)中生成和发行令牌,并以此方式保护REST API。另外,还要在此基础上添加Facebook和Google+登录。但是我正在使用Spring Security迈出初步的步伐,卡在这里了。想知道已经走过这条路的人是否能分享他们的智慧。

你以前有成功过吗? - end-user
@end-user 有一段时间了,所以我不记得我具体是怎么修复它的,但这里是当前工作配置的参考 https://github.com/billrive/billrive/tree/master/billrive-app/src/main/java/com/uhsarp/billrive/spring - user6123723
3个回答

4
您可以将它作为普通的@Configuration类注入,如下所示:
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    FooUserDetailsService fooUserDetailsService;

    @Autowired
    PasswordEncoder passwordEncoder;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .authorizeRequests()
                .antMatchers("/signup").anonymous()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/auth/**").permitAll()
                .antMatchers("/api/**").hasRole("USER")
                .antMatchers("/**").hasAnyRole("USER", "ADMIN")
            .and()
                .csrf().disable()
                .formLogin()
                .loginProcessingUrl("/j_spring_security_check")
                .loginPage("/auth").failureUrl("/auth")
                .usernameParameter("j_username").passwordParameter("j_password")
                .defaultSuccessUrl("/")
            .and()
                .logout()
                .logoutUrl("/j_spring_security_logout")
                .logoutSuccessUrl("/auth");
    }
}

这里的路径只是示例,您可能需要根据自己的需求进行重写,例如如果您正在创建纯REST API,则需要删除表单登录内容。

要加载此内容,可以按照以下步骤操作:

public class WebApplicationInitialiser implements WebApplicationInitializer {

    private static Class<?>[]  configurationClasses = new Class<?>[] {
        WebSecurityConfiguration.class
    };
}

假设您有多个类,使用 createContext(configurationClasses); 将这些类添加到上下文中。

希望我的翻译对您有所帮助。


1
你需要完成“3.4. 授权请求”部分,创建控制器以启用RESTful服务。你可以返回JSON或XML而不是JSP页面。要创建RESTful Web Service,请参考Spring.io文档(http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch18s02.html),这是Spring 3.0的链接,可能有更新版本的Spring 4.0,但此链接应该足以让您开始进行REST方面的工作。一旦您设置了REST请求,例如@RequestMapping("/users/{userid}", method=RequestMethod.GET)
然后您现在可以按照第3.4节,即.antMatchers("/users/**").hasRole("USER")
下一步是查看身份验证并设置包含用户/密码的数据源,这里有两个选项,我建议您首先使用内存配置,请参阅“3.5.1. In Memory Authentication”获取更多信息。

谢谢。但是我无法通过3.2.3节。我不确定如何扩展AbstractSecurityWebApplicationInitializer和/或AbstractAnnotationConfigDispatcherServletInitializer,以及如何与我的现有Config / Initializer类集成。 - user6123723
如果您已经有一个实现WebApplicationInitializer和实现了onStartup方法(加载您的Spring应用程序配置)的类"WebAppInitializer",那么您将使用"AbstractSecurityWebApplicationInitializer"。否则,您将寻找使用AbstractSecurityWebApplicationInitializer方法。 - ebell

0

实际上,注册两个context-loader监听器会触发与框架相关的异常。当通过java-config扩展AbstractAnnotationConfigDispatcherServletInitializer来装饰DispatcherServlet配置时,这两种context-loader监听器注册场景会发生 -> root-config类将在ContextLoaderListener上下文中注册;现在,如果通过扩展AbstractSecurityWebApplicationInitializer启用了安全性方面,将尝试创建另一个ContextLoaderListener,如果给定了任何root-configuration类。因此,建议如果已经有一个带有根相关配置bean的ContextLoaderListener,请避免通过AbstractSecurityWebApplicationInitializer注册其他根相关配置bean。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接