使用SpringMVC初始化Spring-Security

时间:2017-07-26 17:34:03

标签: java spring spring-mvc spring-security

我有一个SpringMVC项目(正在工作)。我决定要测试spring-security库,然后把它放到我的项目中。现在,我收到了这个错误:

var listCoords = (function listCoords(coords, i) {
  if (i && i <= coords.length) console.log(coords[i - 1]);
  setTimeout(listCoords, 5000, coords, ++i)
}(coords, 0));

我尝试修复它将它添加到我的web.xml文件(我的spring-mvc项目)但是然后tomcats崩溃致命错误(没有细节),当我删除此代码时再次正常工作:

    INFORMACIÓN: Starting Servlet Engine: Apache Tomcat/8.0.36
jul 27, 2017 7:17:31 PM org.apache.jasper.servlet.TldScanner scanJars
INFORMACIÓN: Al menos un JAR, que se ha explorado buscando TLDs, aún no contenía TLDs. Activar historial de depuración para este historiador para una completa lista de los JARs que fueron explorados y de los que nos se halló TLDs. Saltarse JARs no necesarios durante la exploración puede dar lugar a una mejora de tiempo significativa en el arranque y compilación de JSP .
jul 27, 2017 7:17:31 PM org.apache.catalina.core.ApplicationContext log
INFORMACIÓN: 1 Spring WebApplicationInitializers detected on classpath
jul 27, 2017 7:17:31 PM org.apache.catalina.core.ApplicationContext log
INFORMACIÓN: Initializing Spring root WebApplicationContext
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization started
INFO : org.springframework.web.context.support.XmlWebApplicationContext - Refreshing Root WebApplicationContext: startup date [Thu Jul 27 19:17:31 CEST 2017]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/root-context.xml]
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 255 ms
jul 27, 2017 7:17:32 PM org.apache.catalina.core.StandardContext filterStart
GRAVE: Excepción arrancando filtro springSecurityFilterChain
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:687)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1207)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1084)

我的安全配置是:

SecurityConfig.java (我的春季安全级别)

<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>

CustomUserDetailService.java 我的用户角色服务(用于弹簧安全)

    package com.myproject.security;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("dataSource")
    DataSource dataSource;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.jdbcAuthentication().dataSource(dataSource);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.authorizeRequests()
                .antMatchers("/", "/register", "/login").access("hasRole('DEFAULT')")
                .antMatchers("/web").access("hasRole('USER')")
                .antMatchers("/admin").access("hasRole('ADMIN')")
                .anyRequest().permitAll()
            .and()
                .formLogin()
                    .loginPage("/login")
                    .usernameParameter("username")
                    .passwordParameter("password")
            .and() 
                .logout()
                    .logoutSuccessUrl("/login?logout")
            .and()
                .exceptionHandling().accessDeniedPage("/403")
            .and()
                .csrf()
            .and()
                .cors();
        // @formatter:on
    }
}

SecurityWebApplicationInitializer.java (此类用于初始化Spring-Security)

    package com.everyhuman.security;

    import java.util.ArrayList;
    import java.util.List;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;

    import com.myproject.web.register.service.ServiceUser;
    import com.myproject.web.users.dto.DTORoles;
    import com.myproject.web.users.dto.DTOUser;


    @Service("customUserDetailService")
    public class CustomUserDetailService implements UserDetailsService {

        private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailService.class);

        @Autowired
        private ServiceUser serviceUser;

        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            DTOUser user = serviceUser.findUserByUsername(username);
            if (user == null) {
                logger.info("User not found");
                throw new UsernameNotFoundException("Username not found");
            }

            /*
             * Devolvemos un usuario securizado por spring
             */
            return new User(user.getUsername(), user.getPassword(), getGrantedAuthorities(user));
        }

        /**
         * Obtiene los roles del usuario
         * 
         * @param user
         * @return
         */
        private List<GrantedAuthority> getGrantedAuthorities(DTOUser user) {
            List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

            for (DTORoles userProfile : user.getRoles()) {
                authorities.add(new SimpleGrantedAuthority(userProfile.toString()));
            }
            return authorities;
        }

    }

这是我的春季配置:

    package com.myproject.security;

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

    public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

    }

这是我的web.xml配置:

    <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">

    <annotation-driven />

    <resources mapping="/resources/**" location="/resources/" />

    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.myproject">
        <context:include-filter type="regex" expression="com.myproject.*.controller.*"/>
    </context:component-scan>

    <context:property-placeholder location="classpath:ehconf/*.properties" />

    <beans:bean id="myEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="packagesToScan" value = "com.myproject.web" />
        <beans:property name="jpaVendorAdapter">
            <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
        </beans:property>
        <beans:property name="jpaProperties">
            <beans:props>
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</beans:prop>
            </beans:props>
        </beans:property>
   </beans:bean>

   <beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <beans:property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
      <beans:property name="url" value="jdbc:mysql://localhost:3306/ehdatabase?serverTimezone=UTC" />
      <beans:property name="username" value="ehdatabase" />
      <beans:property name="password" value="ehdatabase123" />
   </beans:bean>

   <beans:bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
      <beans:property name="entityManagerFactory" ref="myEmf" />
   </beans:bean>

   <tx:annotation-driven />

   <beans:bean id="persistenceExceptionTranslationPostProcessor" 
   class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

</beans:beans>

2 个答案:

答案 0 :(得分:2)

我建议你坚持使用Java Config,因为你使用的是Tomcat 8

请注意,如果您有

,则不需要XML安全性部分
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {

}

所以你可以删除

<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>

然后,确保将包含secuirty配置的包添加到组件扫描

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.myproject.security")
public class HelloWorldConfiguration {

    @Bean
    public ViewResolver viewResolver() {
        //InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        //viewResolver.setViewClass(JstlView.class);
        //viewResolver.setPrefix("/WEB-INF/views/");
        //viewResolver.setSuffix(".jsp");
        // Set View Resolver

        return viewResolver;
    }

}

您也可以删除web.xml并改为使用

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

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

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

有关完整示例,请检查http://websystique.com/spring-security/spring-security-4-hello-world-annotation-xml-example/

对于JPA Config,您可以添加类似

的内容
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = { "com.myproject.repository" })
public class PersistenceJPAConfig {
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { "com.myproject.jpa.entites"});

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());

        return em;
    }

    private DatabasePopulator createDatabasePopulator() {
        ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator();
        databasePopulator.setContinueOnError(true);
        databasePopulator.addScript(new ClassPathResource("dropdownlist.sql"));
//        databasePopulator.addScript(new ClassPathResource("persistentlogins.sql"));
//        databasePopulator.addScript(new ClassPathResource("countries.sql"));
//        databasePopulator.addScript(new ClassPathResource("states.sql"));
//        databasePopulator.addScript(new ClassPathResource("cities.sql"));

        return databasePopulator;
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
//      dataSource.setDriverClassName("com.mysql.jdbc.Driver");
//      dataSource.setUrl("jdbc:mysql://localhost:3306/spring_jpa");
//      dataSource.setUsername("tutorialuser");
//      dataSource.setPassword("tutorialmy5ql");
        dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
        dataSource.setUrl("jdbc:sqlserver://localhost\\SQLEXPRESS;databaseName=ContractTracker");
        dataSource.setUsername("ctReader");
        dataSource.setPassword("ctreader");

        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);

        DatabasePopulatorUtils.execute(createDatabasePopulator(), dataSource());

        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServerDialect");
        return properties;
    }
}

答案 1 :(得分:1)

已编辑:您是否尝试添加bean deffinition?

<bean id="springSecurityFilterChain" class="org.springframework.web.filter.DelegatingFilterProxy"/>

另一个可能的失败是我无法在你的配置中看到启动spring上下文的监听器:

<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>

查看Spring页面了解详情。

OLD:由于信誉不佳,我无法添加评论,所以您可以发布您的web.xml和security.xml吗?