【问题标题】:Spring MVC and Spring Security IntegrationSpring MVC 和 Spring 安全集成
【发布时间】:2021-04-01 11:39:19
【问题描述】:

我正在尝试在我的项目中加入安全性。我从互联网上找到了一个示例,但我无法实现正确的集成。

在我的依赖项下,

    <properties>
        <java-version>1.8</java-version>
        <org.springframework-version>5.2.9.RELEASE</org.springframework-version>
        <org.hibernate-validator-version>5.4.1.Final</org.hibernate-validator-version>
        <org.hibernate-core-version>5.3.7.Final</org.hibernate-core-version>
        <c3p0-version>0.9.5.2</c3p0-version>
        <mysql-version>5.1.47</mysql-version>
        <spring.version>5.4.1</spring.version>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <!-- Spring MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <!-- Spring ORM -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
        <!-- Hibernate Validator -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${org.hibernate-validator-version}</version>
        </dependency>
        <!-- Hibernate Core Libs -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${org.hibernate-core-version}</version>
        </dependency>
        <!-- C3P0 Libs -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>${c3p0-version}</version>
        </dependency>
        <!-- MySQL JDBC Lib -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-version}</version>
        </dependency>
        <!-- JSTL Libs -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
        </dependency>
        <!-- Tag Libs -->
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!-- JSP Libs -->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- Spring Security Core -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
         
        <!-- Spring Security Config -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${spring.version}</version>
        </dependency>
         
        <!-- Spring Security Web -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-jpa -->
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-jpa</artifactId>
            <version>2.4.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
        <dependency>
           <groupId>commons-beanutils</groupId>
           <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
       </dependency>                
       <!-- https://mvnrepository.com/artifact/javax.validation/validation-api -->
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>  
    </dependencies>

Project Structure

我的 AppContext,

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@PropertySource("classpath:database.properties")
@EnableTransactionManagement
public class AppContextX {

    @Autowired
    private Environment environmentX;
    
    @Bean
    public LocalSessionFactoryBean XSessionFactory() {
        LocalSessionFactoryBean sessionFactoryX = new LocalSessionFactoryBean();
        sessionFactoryX.setDataSource(dataSource());
        sessionFactoryX.setPackagesToScan(new String[] {"com.mutfakapp.xmutfak.entity"});
        sessionFactoryX.setHibernateProperties(XHibernateProperties());
        return sessionFactoryX;
    }
    
    
    private Properties XHibernateProperties() {
        Properties propertiesX = new Properties();
        propertiesX.put("hibernate.dialect", environmentX.getRequiredProperty("hibernate.dialect"));
        propertiesX.put("hibernate.show_sql",environmentX.getRequiredProperty("hibernate.show_sql"));
        propertiesX.put("hibernate.format_sql", environmentX.getRequiredProperty("hibernate.format_sql"));
        propertiesX.put("hibernate.hbm2ddl.auto", environmentX.getRequiredProperty("hibernate.hbm2ddl"));
        return propertiesX;
    }
    
    private DataSource dataSource() {
        DriverManagerDataSource dataSourceX = new DriverManagerDataSource();
        dataSourceX.setDriverClassName(environmentX.getRequiredProperty("jdbc.driverClassName"));
        dataSourceX.setUrl(environmentX.getRequiredProperty("jdbc.url"));
        dataSourceX.setUsername(environmentX.getRequiredProperty("jdbc.username"));
        dataSourceX.setPassword(environmentX.getRequiredProperty("jdbc.password"));
        return dataSourceX;
    }
    
    @Bean
    public HibernateTransactionManager getTransactionManager() {
        HibernateTransactionManager transactionManagerX = new HibernateTransactionManager();
        transactionManagerX.setSessionFactory(XSessionFactory().getObject());
        return transactionManagerX;
    }
}

数据库属性,

#JDBC
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/testdb?useSSL=false
jdbc.username=root
jdbc.password=123

#Hibernate
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
hibernate.format_sql=true
hibernate.hbm2ddl=update

我的应用初始化器,

package com.mutfakapp.xmutfak.config;

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

public class AppInitializerX extends AbstractAnnotationConfigDispatcherServletInitializer
{

    @Override
    protected Class<?>[] getRootConfigClasses() {

        return new Class[] {AppContextX.class};
        
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {

        return new Class[] {WebMvcConfigX.class};
        
    }

    @Override
    protected String[] getServletMappings() {

        return new String[] { "/" };
    }

}

WebMvcConfig 如下,

package com.mutfakapp.xmutfak.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

@Configuration
@EnableWebSecurity
@EnableWebMvc
@ComponentScan(basePackages = {"com.mutfakapp.xmutfak"})
@Import({ WebSecurityConfig.class })
public class WebMvcConfigX implements WebMvcConfigurer {

    @Bean
    public InternalResourceViewResolver XResolver() {
        InternalResourceViewResolver resolverX = new InternalResourceViewResolver();
        resolverX.setViewClass(JstlView.class);
        resolverX.setPrefix("/WEB-INF/views/");
        resolverX.setSuffix(".jsp");
        return resolverX;
    }
    
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }
    
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

}

和网络安全配置

package com.mutfakapp.xmutfak.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.mutfakapp.xmutfak.service.UserService;

@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers(
                "/",
                "/home",
                "/lunch",
                "/dinner",
                "/registration").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().defaultSuccessUrl("/addreceipt")
            .loginPage("/login")
            .permitAll()
            .and()
            .logout()
            .invalidateHttpSession(true)
            .clearAuthentication(true)
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/login?logout")
            .permitAll();
    }

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

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }
}

当我运行项目时,出现以下错误。我想不通。

SEVERE: Exception starting filter [springSecurityFilterChain]
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'springSecurityFilterChain' available
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:816)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1288)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1115)
    at org.springframework.web.filter.DelegatingFilterProxy.initDelegate(DelegatingFilterProxy.java:338)
    at org.springframework.web.filter.DelegatingFilterProxy.initFilterBean(DelegatingFilterProxy.java:243)
    at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:239)
    at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:270)
    at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:106)
    at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4566)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5203)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:843)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1384)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1374)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:909)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:421)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:930)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:772)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:342)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:473)

【问题讨论】:

    标签: java spring spring-mvc spring-security


    【解决方案1】:

    我了解到您是 Spring 新手,您尝试使用 Spring MVC 和 Spring Security 准备简单的 Hello World 项目。如果是这样,我建议使用 Spring Boot。它为 Spring 项目提供自动配置。

    您可以使用Spring Initializr 生成项目。只需添加所需的依赖项:Spring Web - MVC 和 Spring Security。我看到您使用 Hibernate - 将此 ORM 与 Spring 应用程序一起使用的最简单方法是使用 Spring Data JPA。您还需要用于数据库连接的 JDBC 驱动程序(这里是 MySQL)。

    之后,您可以下载您的应用程序 - 一切就绪。 您应该在 src/main/resources/application.properties 文件中定义访问数据库的属性:

    spring.datasource.url=jdbc:mysql://localhost:3306/testdb
    spring.datasource.username=root
    spring.datasource.password=123
    spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
    spring.jpa.hibernate.ddl-auto=update
    

    您还应该使用安全配置创建类。

    import org.springframework.context.annotation.Configuration;
    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;
    
    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/hello").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin().permitAll();
        }
    }
    

    还有简单的控制器:

    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class MyController {
        @GetMapping(value = {"/", "/hello"})
        public String hello() {
            return "Hello";
        }
    
        @GetMapping("/secret")
        public String secret() {
            return "Only for signed in users";
        }
    }
    

    当您启动应用程序时,您会看到为用户生成的密码:

    Using generated security password: 609ebedd-605e-4045-b6fd-5930b53720a2
    

    当您转到 localhost:8080:hello 时,您将看到消息“Hello”。 当你去 localhost:8080/secret 访问将被禁止。您必须使用生成的密码以“用户”身份登录。

    在这个例子中,我只连接数据库,但我不使用它——就像你在你的应用程序中一样。

    如果你想看到你与数据库创建实体连接:

    @Entity
    class Car {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Column(unique = true)
        private String name;
    
    //plus getters, setters, equals, hashCode
    }
    

    和存储库:

    interface CarRepository extends JpaRepository<Car, Long> {
    }
    

    您的数据库中的表将在应用程序启动时创建。

    【讨论】:

    • 我必须做 spring mvc 项目,因为我的课程要求你有什么解决方案。谢谢你的回答。
    • 你仍然会使用 Spring MVC,Spring Boot 只会让事情变得更简单和更容易实现。除非您明确要求不要使用 Spring Boot,否则我看不出至少不尝试的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    • 1970-01-01
    • 2015-03-05
    • 2013-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多