Spring 使用 Java EE Restful 服务的安全性

Spring Security with Java EE Restful Service

我创建了一个 Java EE 6 restfull 服务,并尝试将其与 Spring 安全性集成。但是,我总是遇到不同的奇怪异常。这没有任何意义或可能有意义,但至少对我来说不是。

我的应用程序的方向结构是这样的:

com.security
    UserDetailsSecurityConfig.java
com.service
    ApplicationConfig.java
    UserFacadeREST.java
com.config
    AppConfig.java

我的实体是自动生成的,所以似乎没有错误。但是,是的,这三个文件对我来说似乎很可疑,因为当我不将我的应用程序与 Spring Security.

集成时,UserFacadeREST 工作正常

com.UserDetailsSecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class UserDetailsSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService( userDetailsService() );
    }
    @Override
    protected void configure( HttpSecurity http ) throws Exception {
        http
           .httpBasic().and()
           .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS ).and()
           .authorizeRequests().antMatchers("/**").hasRole( "USER" );
    }
    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername( final String username ) 
                    throws UsernameNotFoundException {
                if( username.equals( "admin" ) ) {
                    return new User( username, "password", true, true, true, true,
                            Arrays.asList(
                            new SimpleGrantedAuthority("ROLE_USER" ),
                            new SimpleGrantedAuthority( "ROLE_ADMIN" )
                        )
                    );
                } else if ( username.equals( "user" ) ) {
                    return new User( username, "password", true, true, true, true,
                        Arrays.asList(
                            new SimpleGrantedAuthority( "ROLE_USER" )
                        )
                    );
                } 

                return null;
            }
        };
    }

}

com.service.ApplicationConfig.java

@javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> resources = new java.util.HashSet<>();
        addRestResourceClasses(resources);
        return resources;
    }

    /**
     * Do not modify addRestResourceClasses() method.
     * It is automatically populated with
     * all resources defined in the project.
     * If required, comment out calling this method in getClasses().
     */
    private void addRestResourceClasses(Set<Class<?>> resources) {
        resources.add(com.service.UserFacadeREST.class);
    }

}

com.service.UserFacadeREST.java

@Stateless
@Path("user")
public class UserFacadeREST extends AbstractFacade<UpUser> {
    @PersistenceContext(unitName = "PU")
    private EntityManager em;

    public UserFacadeREST() {
        super(User.class);
    }

    @POST
    @Override
    @Consumes({"application/xml", "application/json"})
    public void create(User entity) {
        super.create(entity);
    }
    @GET
    @Path("count")
    @Produces("text/plain")
    public String countREST() {
        return String.valueOf(super.count());
    }

}

com.config.AppConfig.java

@Configuration
@Import( UserDetailsSecurityConfig.class )
public class AppConfig {    
    @Bean 
    public ApplicationConfig applicationConfig() {
        return new ApplicationConfig();
    }
        @Bean 
    public UserFacadeREST userRestService() {
        return new UserFacadeREST();
    }   


}

在整个代码中,我对点击和试用做了一些改动。目前,我遇到了异常。

java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?

在此之前,我遇到了另一个异常

WebSecurityConfigurers must be unique. Order of 100 was already used

在将 Spring 安全与 Java EE 6 集成时,我没有弄错我在做什么。我是 Spring 的新手,所以我可能犯了一个错误对我来说很明显。

我的 web.xml 文件是:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="rest-sec" version="3.0">

    <display-name>rest</display-name>

    <!-- Spring security -->
    <listener>
        <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>etagFilter</filter-name>
        <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>etagFilter</filter-name>
        <url-pattern>/api/*</url-pattern>
    </filter-mapping>

    <!-- rest -->
    <servlet>
        <servlet-name>rest</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.labs.entities</param-value> <!-- won't find anything -->
        </init-param>
        <init-param>
            <param-name>dispatchOptionsRequest</param-name>
            <param-value>true</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>rest</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

    <!-- Disables servlet container welcome file handling. Needed for compatibility 
        with Servlet 3.0 and Tomcat 7.0 -->
    <welcome-file-list>
        <welcome-file />
    </welcome-file-list>

</web-app>

java.lang.IllegalStateException: No WebApplicationContext found: no ContextLoaderListener registered?

您需要告诉过滤器在哪里寻找您的上下文(默认情况下是在您创建的 servlet 未使用的地方寻找)。在您的过滤器中添加一个初始化参数:

    <init-param>
        <param-name>contextAttribute</param-name>
        <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
    </init-param>

WebSecurityConfigurers must be unique. Order of 100 was already used

你有 2 个 WebSecurityConfigurerAdapter 类型的豆子吗?还是您的 UserDetailsSecurityConfig 被加载了两次?