简体   繁体   中英

Spring MVC and Spring Security Integration

I am trying to spring security into my project. I have found a sample from internet but I could not achieve correct integration.

Below my dependencies,

    <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

My 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;
    }
}

Database properties,

#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

My App Initializer,

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 as below,

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();
    }

}

And Web Security Configuration

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

When I run the project I am getting following error. I could not figure out.

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)

I understood you are new in Spring and you try to prepare simple Hello World project using Spring MVC and Spring Security. If so I recomend to use Spring Boot. It provide auto-configuration for Spring projects.

You can generate project using Spring Initializr . Just add needed dependencies: Spring Web - MVC and Spring Security. I see you use Hibernate - the easiest way to use this ORM with Spring application is to use Spring Data JPA. You will need also JDBC driver for database connection (here MySQL).

弹簧初始化器

After that you can download your application - it's ready to go. You should define properties to access your database in src/main/resources/application.properties file:

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

You should also create class with secutiry configuration.

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();
    }
}

And simple controller:

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";
    }
}

When you launch application youu see generated password for user:

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

When you go to localhost:8080:hello you will see message "Hello". When you go to localhost:8080/secret access will be forbidden. You have to go sign in as "user" with generated password.

In this example I only connect with database, but I don't use it - as you in your application.

If you want to see you are connected with database create entity:

@Entity
class Car {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String name;

//plus getters, setters, equals, hashCode
}

And repository:

interface CarRepository extends JpaRepository<Car, Long> {
}

Table in your database will be create when application starts.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM