rename project (#1144)
This commit is contained in:
parent
84ecb92f45
commit
88deec0162
|
@ -0,0 +1,7 @@
|
|||
###The Course
|
||||
The "REST With Spring" Classes: http://github.learnspringsecurity.com
|
||||
|
||||
###Relevant Articles:
|
||||
- [A Custom Security Expression with Spring Security](http://www.baeldung.com/spring-security-create-new-custom-security-expression)
|
||||
- [Custom AccessDecisionVoters in Spring Security](http://www.baeldung.com/spring-security-custom-voter)
|
||||
- [Spring Security: Authentication with a Database-backed UserDetailsService](http://www.baeldung.com/spring-security-authentication-with-a-database)
|
|
@ -0,0 +1,3 @@
|
|||
Manifest-Version: 1.0
|
||||
Class-Path:
|
||||
|
|
@ -0,0 +1,303 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-security-mvc-boot</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>spring-security-mvc-boot</name>
|
||||
<description>Spring Security MVC Boot</description>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.4.2.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf.extras</groupId>
|
||||
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jayway.restassured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<version>${rest-assured.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
<version>${derby.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbyclient</artifactId>
|
||||
<version>${derby.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbynet</artifactId>
|
||||
<version>${derby.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbytools</artifactId>
|
||||
<version>${derby.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>taglibs</groupId>
|
||||
<artifactId>standard</artifactId>
|
||||
<version>${taglibs-standard.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-taglibs</artifactId>
|
||||
<version>${spring-security-taglibs.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-core</artifactId>
|
||||
<version>${spring-security-core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet.jsp.jstl</groupId>
|
||||
<artifactId>jstl-api</artifactId>
|
||||
<version>${jstl.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*IntegrationTest.java</exclude>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
<systemPropertyVariables>
|
||||
<!-- <provPersistenceTarget>h2</provPersistenceTarget> -->
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<version>${cargo-maven2-plugin.version}</version>
|
||||
<configuration>
|
||||
<wait>true</wait>
|
||||
<container>
|
||||
<containerId>tomcat8x</containerId>
|
||||
<type>embedded</type>
|
||||
<systemProperties>
|
||||
<!-- <provPersistenceTarget>cargo</provPersistenceTarget> -->
|
||||
</systemProperties>
|
||||
</container>
|
||||
<configuration>
|
||||
<properties>
|
||||
<cargo.servlet.port>8082</cargo.servlet.port>
|
||||
</properties>
|
||||
</configuration>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<test.mime>json</test.mime>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>live</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-server</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-server</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>stop</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>none</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*LiveTest.java</include>
|
||||
</includes>
|
||||
<systemPropertyVariables>
|
||||
<webTarget>cargo</webTarget>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
<properties>
|
||||
<start-class>org.baeldung.Application</start-class>
|
||||
<!--If you want to run the example with the voters comment the tag above and uncomment the one below-->
|
||||
<!--<start-class>org.baeldung.voter.VoterApplication</start-class>-->
|
||||
<!--If you want to run the example with the multiple logins, comment the tag above and uncomment the one below-->
|
||||
<!--<start-class>org.baeldung.multiplelogin.MultipleLoginApplication</start-class>-->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<derby.version>10.13.1.1</derby.version>
|
||||
<taglibs-standard.version>1.1.2</taglibs-standard.version>
|
||||
<spring-security-taglibs.version>4.2.0.RELEASE</spring-security-taglibs.version>
|
||||
<spring-security-core.version>4.2.0.RELEASE</spring-security-core.version>
|
||||
|
||||
<jstl.version>1.2</jstl.version>
|
||||
<rest-assured.version>2.4.0</rest-assured.version>
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,17 @@
|
|||
package org.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.context.web.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.voter.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multiplelogin.*")})
|
||||
public class Application extends SpringBootServletInitializer {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.baeldung.config;
|
||||
|
||||
import org.baeldung.security.CustomMethodSecurityExpressionHandler;
|
||||
import org.baeldung.security.CustomPermissionEvaluator;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
|
||||
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
|
||||
|
||||
@Override
|
||||
protected MethodSecurityExpressionHandler createExpressionHandler() {
|
||||
// final DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
|
||||
final CustomMethodSecurityExpressionHandler expressionHandler = new CustomMethodSecurityExpressionHandler();
|
||||
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
|
||||
return expressionHandler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.baeldung.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
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.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class MvcConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
public MvcConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
//
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewControllers(final ViewControllerRegistry registry) {
|
||||
super.addViewControllers(registry);
|
||||
registry.addViewController("/").setViewName("forward:/index");
|
||||
registry.addViewController("/index");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package org.baeldung.config;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
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.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@PropertySource({ "classpath:persistence-derby.properties" })
|
||||
@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao")
|
||||
public class PersistenceConfig {
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
|
||||
public PersistenceConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
// beans
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource());
|
||||
em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
|
||||
|
||||
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
em.setJpaVendorAdapter(vendorAdapter);
|
||||
em.setJpaProperties(additionalProperties());
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
|
||||
dataSource.setUrl(env.getProperty("jdbc.url"));
|
||||
dataSource.setUsername(env.getProperty("jdbc.user"));
|
||||
dataSource.setPassword(env.getProperty("jdbc.pass"));
|
||||
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
|
||||
final JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||
transactionManager.setEntityManagerFactory(emf);
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
|
||||
final Properties additionalProperties() {
|
||||
final Properties hibernateProperties = new Properties();
|
||||
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
|
||||
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
|
||||
hibernateProperties.setProperty("hibernate.cache.use_second_level_cache", env.getProperty("hibernate.cache.use_second_level_cache"));
|
||||
hibernateProperties.setProperty("hibernate.cache.use_query_cache", env.getProperty("hibernate.cache.use_query_cache"));
|
||||
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
|
||||
return hibernateProperties;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.baeldung.config;
|
||||
|
||||
import org.baeldung.security.MyUserDetailsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
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.builders.WebSecurity;
|
||||
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.crypto.password.PasswordEncoder;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@ComponentScan("org.baeldung.security")
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private MyUserDetailsService userDetailsService;
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/resources/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/login").permitAll()
|
||||
.antMatchers("/admin").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.and().formLogin().permitAll()
|
||||
.and().csrf().disable();
|
||||
;
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authenticationProvider() {
|
||||
final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
authProvider.setUserDetailsService(userDetailsService);
|
||||
authProvider.setPasswordEncoder(encoder());
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder encoder() {
|
||||
return new BCryptPasswordEncoder(11);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.baeldung.multiplelogin;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.context.web.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan("org.baeldung.multiplelogin")
|
||||
public class MultipleLoginApplication extends SpringBootServletInitializer {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MultipleLoginApplication.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(MultipleLoginApplication.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package org.baeldung.multiplelogin;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
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.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
import org.springframework.web.servlet.view.JstlView;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@EnableWebMvc
|
||||
@Configuration
|
||||
@ComponentScan("org.baeldung.controller")
|
||||
public class MultipleLoginMvcConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
public MultipleLoginMvcConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
@Override
|
||||
public void addViewControllers(final ViewControllerRegistry registry) {
|
||||
super.addViewControllers(registry);
|
||||
|
||||
registry.addViewController("/anonymous.html");
|
||||
|
||||
registry.addViewController("/login.html");
|
||||
registry.addViewController("/homepage.html");
|
||||
registry.addViewController("/console.html");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewResolver viewResolver() {
|
||||
final InternalResourceViewResolver bean = new InternalResourceViewResolver();
|
||||
|
||||
bean.setViewClass(JstlView.class);
|
||||
bean.setPrefix("/WEB-INF/view/");
|
||||
bean.setSuffix(".jsp");
|
||||
|
||||
return bean;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package org.baeldung.multiplelogin;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.TestingAuthenticationProvider;
|
||||
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;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class MultipleLoginSecurityConfig {
|
||||
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() throws Exception {
|
||||
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
|
||||
manager.createUser(User.withUsername("user")
|
||||
.password("userPass")
|
||||
.roles("USER")
|
||||
.build());
|
||||
manager.createUser(User.withUsername("admin")
|
||||
.password("adminPass")
|
||||
.roles("ADMIN")
|
||||
.build());
|
||||
return manager;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(1)
|
||||
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public App1ConfigurationAdapter() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("admin")
|
||||
.password("admin")
|
||||
.roles("ADMIN");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.antMatcher("/admin*")
|
||||
.authorizeRequests()
|
||||
.anyRequest()
|
||||
.hasRole("ADMIN")
|
||||
// log in
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage("/loginAdmin")
|
||||
.loginProcessingUrl("/admin_login")
|
||||
.failureUrl("/loginAdmin?error=loginError")
|
||||
.defaultSuccessUrl("/adminPage")
|
||||
// logout
|
||||
.and()
|
||||
.logout()
|
||||
.logoutUrl("/admin_logout")
|
||||
.logoutSuccessUrl("/protectedLinks")
|
||||
.deleteCookies("JSESSIONID")
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.accessDeniedPage("/403")
|
||||
.and()
|
||||
.csrf()
|
||||
.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Order(2)
|
||||
public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
public App2ConfigurationAdapter() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.inMemoryAuthentication()
|
||||
.withUser("user")
|
||||
.password("user")
|
||||
.roles("USER");
|
||||
}
|
||||
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.antMatcher("/user*")
|
||||
.authorizeRequests()
|
||||
.anyRequest()
|
||||
.hasRole("USER")
|
||||
// log in
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage("/loginUser")
|
||||
.loginProcessingUrl("/user_login")
|
||||
.failureUrl("/loginUser?error=loginError")
|
||||
.defaultSuccessUrl("/userPage")
|
||||
// logout
|
||||
.and()
|
||||
.logout()
|
||||
.logoutUrl("/user_logout")
|
||||
.logoutSuccessUrl("/protectedLinks")
|
||||
.deleteCookies("JSESSIONID")
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.accessDeniedPage("/403")
|
||||
.and()
|
||||
.csrf()
|
||||
.disable();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.baeldung.multiplelogin;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class UsersController {
|
||||
|
||||
@RequestMapping("/protectedLinks")
|
||||
public String getAnonymousPage() {
|
||||
return "protectedLinks";
|
||||
}
|
||||
|
||||
@RequestMapping("/userPage")
|
||||
public String getUserPage() {
|
||||
return "userPage";
|
||||
}
|
||||
|
||||
@RequestMapping("/adminPage")
|
||||
public String getAdminPage() {
|
||||
return "adminPage";
|
||||
}
|
||||
|
||||
@RequestMapping("/loginAdmin")
|
||||
public String getAdminLoginPage() {
|
||||
return "loginAdmin";
|
||||
}
|
||||
|
||||
@RequestMapping("/loginUser")
|
||||
public String getUserLoginPage() {
|
||||
return "loginUser";
|
||||
}
|
||||
|
||||
@RequestMapping("/403")
|
||||
public String getAccessDeniedPage() {
|
||||
return "403";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package org.baeldung.persistence;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
import org.baeldung.persistence.dao.OrganizationRepository;
|
||||
import org.baeldung.persistence.dao.PrivilegeRepository;
|
||||
import org.baeldung.persistence.dao.UserRepository;
|
||||
import org.baeldung.persistence.model.Organization;
|
||||
import org.baeldung.persistence.model.Privilege;
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class SetupData {
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private PrivilegeRepository privilegeRepository;
|
||||
|
||||
@Autowired
|
||||
private OrganizationRepository organizationRepository;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initOrganizations();
|
||||
initPrivileges();
|
||||
initUsers();
|
||||
}
|
||||
|
||||
private void initUsers() {
|
||||
final Privilege privilege1 = privilegeRepository.findByName("FOO_READ_PRIVILEGE");
|
||||
final Privilege privilege2 = privilegeRepository.findByName("FOO_WRITE_PRIVILEGE");
|
||||
//
|
||||
final User user1 = new User();
|
||||
user1.setUsername("john");
|
||||
user1.setPassword("123");
|
||||
user1.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1)));
|
||||
user1.setOrganization(organizationRepository.findByName("FirstOrg"));
|
||||
userRepository.save(user1);
|
||||
//
|
||||
final User user2 = new User();
|
||||
user2.setUsername("tom");
|
||||
user2.setPassword("111");
|
||||
user2.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1, privilege2)));
|
||||
user2.setOrganization(organizationRepository.findByName("SecondOrg"));
|
||||
userRepository.save(user2);
|
||||
}
|
||||
|
||||
private void initOrganizations() {
|
||||
final Organization org1 = new Organization("FirstOrg");
|
||||
organizationRepository.save(org1);
|
||||
//
|
||||
final Organization org2 = new Organization("SecondOrg");
|
||||
organizationRepository.save(org2);
|
||||
}
|
||||
|
||||
private void initPrivileges() {
|
||||
final Privilege privilege1 = new Privilege("FOO_READ_PRIVILEGE");
|
||||
privilegeRepository.save(privilege1);
|
||||
//
|
||||
final Privilege privilege2 = new Privilege("FOO_WRITE_PRIVILEGE");
|
||||
privilegeRepository.save(privilege2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.baeldung.persistence.dao;
|
||||
|
||||
import org.baeldung.persistence.model.Organization;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface OrganizationRepository extends JpaRepository<Organization, Long> {
|
||||
|
||||
public Organization findByName(String name);
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.baeldung.persistence.dao;
|
||||
|
||||
import org.baeldung.persistence.model.Privilege;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface PrivilegeRepository extends JpaRepository<Privilege, Long> {
|
||||
|
||||
public Privilege findByName(String name);
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package org.baeldung.persistence.dao;
|
||||
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
|
||||
User findByUsername(final String username);
|
||||
|
||||
@Transactional
|
||||
void removeUserByUsername(String username);
|
||||
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package org.baeldung.persistence.model;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Foo {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
//
|
||||
|
||||
public Foo() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Foo(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Foo [id=").append(id).append(", name=").append(name).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = (prime * result) + ((id == null) ? 0 : id.hashCode());
|
||||
result = (prime * result) + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Foo other = (Foo) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package org.baeldung.persistence.model;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Organization {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
//
|
||||
|
||||
public Organization() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Organization(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Organization [id=").append(id).append(", name=").append(name).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = (prime * result) + ((id == null) ? 0 : id.hashCode());
|
||||
result = (prime * result) + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Organization other = (Organization) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package org.baeldung.persistence.model;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Privilege {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
//
|
||||
|
||||
public Privilege() {
|
||||
super();
|
||||
}
|
||||
|
||||
public Privilege(String name) {
|
||||
super();
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("Privilege [id=").append(id).append(", name=").append(name).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = (prime * result) + ((id == null) ? 0 : id.hashCode());
|
||||
result = (prime * result) + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Privilege other = (Privilege) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (name == null) {
|
||||
if (other.name != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!name.equals(other.name)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
package org.baeldung.persistence.model;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "user_table")
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "users_privileges", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id"))
|
||||
private Set<Privilege> privileges;
|
||||
|
||||
@ManyToOne(fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "organization_id", referencedColumnName = "id")
|
||||
private Organization organization;
|
||||
|
||||
//
|
||||
|
||||
public User() {
|
||||
super();
|
||||
}
|
||||
|
||||
//
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public Set<Privilege> getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
|
||||
public void setPrivileges(Set<Privilege> privileges) {
|
||||
this.privileges = privileges;
|
||||
}
|
||||
|
||||
public Organization getOrganization() {
|
||||
return organization;
|
||||
}
|
||||
|
||||
public void setOrganization(Organization organization) {
|
||||
this.organization = organization;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("User [id=").append(id).append(", username=").append(username).append(", password=").append(password).append(", privileges=").append(privileges).append(", organization=").append(organization).append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = (prime * result) + ((id == null) ? 0 : id.hashCode());
|
||||
result = (prime * result) + ((organization == null) ? 0 : organization.hashCode());
|
||||
result = (prime * result) + ((password == null) ? 0 : password.hashCode());
|
||||
result = (prime * result) + ((privileges == null) ? 0 : privileges.hashCode());
|
||||
result = (prime * result) + ((username == null) ? 0 : username.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final User other = (User) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!id.equals(other.id)) {
|
||||
return false;
|
||||
}
|
||||
if (organization == null) {
|
||||
if (other.organization != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!organization.equals(other.organization)) {
|
||||
return false;
|
||||
}
|
||||
if (password == null) {
|
||||
if (other.password != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!password.equals(other.password)) {
|
||||
return false;
|
||||
}
|
||||
if (privileges == null) {
|
||||
if (other.privileges != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!privileges.equals(other.privileges)) {
|
||||
return false;
|
||||
}
|
||||
if (username == null) {
|
||||
if (other.username != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!username.equals(other.username)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.baeldung.security;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
|
||||
private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
@Override
|
||||
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
|
||||
// final CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
|
||||
final MySecurityExpressionRoot root = new MySecurityExpressionRoot(authentication);
|
||||
root.setPermissionEvaluator(getPermissionEvaluator());
|
||||
root.setTrustResolver(this.trustResolver);
|
||||
root.setRoleHierarchy(getRoleHierarchy());
|
||||
return root;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package org.baeldung.security;
|
||||
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
|
||||
|
||||
private Object filterObject;
|
||||
private Object returnObject;
|
||||
|
||||
public CustomMethodSecurityExpressionRoot(Authentication authentication) {
|
||||
super(authentication);
|
||||
}
|
||||
|
||||
//
|
||||
public boolean isMember(Long OrganizationId) {
|
||||
final User user = ((MyUserPrincipal) this.getPrincipal()).getUser();
|
||||
return user.getOrganization().getId().longValue() == OrganizationId.longValue();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public Object getFilterObject() {
|
||||
return this.filterObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getReturnObject() {
|
||||
return this.returnObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilterObject(Object obj) {
|
||||
this.filterObject = obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReturnObject(Object obj) {
|
||||
this.returnObject = obj;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.baeldung.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class CustomPermissionEvaluator implements PermissionEvaluator {
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Authentication auth, Object targetDomainObject, Object permission) {
|
||||
if ((auth == null) || (targetDomainObject == null) || !(permission instanceof String)) {
|
||||
return false;
|
||||
}
|
||||
final String targetType = targetDomainObject.getClass().getSimpleName().toUpperCase();
|
||||
return hasPrivilege(auth, targetType, permission.toString().toUpperCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Authentication auth, Serializable targetId, String targetType, Object permission) {
|
||||
if ((auth == null) || (targetType == null) || !(permission instanceof String)) {
|
||||
return false;
|
||||
}
|
||||
return hasPrivilege(auth, targetType.toUpperCase(), permission.toString().toUpperCase());
|
||||
}
|
||||
|
||||
private boolean hasPrivilege(Authentication auth, String targetType, String permission) {
|
||||
for (final GrantedAuthority grantedAuth : auth.getAuthorities()) {
|
||||
System.out.println("here " + grantedAuth);
|
||||
if (grantedAuth.getAuthority().startsWith(targetType)) {
|
||||
if (grantedAuth.getAuthority().contains(permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package org.baeldung.security;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
|
||||
public class MySecurityExpressionRoot implements MethodSecurityExpressionOperations {
|
||||
protected final Authentication authentication;
|
||||
private AuthenticationTrustResolver trustResolver;
|
||||
private RoleHierarchy roleHierarchy;
|
||||
private Set<String> roles;
|
||||
private String defaultRolePrefix = "ROLE_";
|
||||
|
||||
public final boolean permitAll = true;
|
||||
public final boolean denyAll = false;
|
||||
private PermissionEvaluator permissionEvaluator;
|
||||
public final String read = "read";
|
||||
public final String write = "write";
|
||||
public final String create = "create";
|
||||
public final String delete = "delete";
|
||||
public final String admin = "administration";
|
||||
|
||||
//
|
||||
|
||||
private Object filterObject;
|
||||
private Object returnObject;
|
||||
|
||||
public MySecurityExpressionRoot(Authentication authentication) {
|
||||
if (authentication == null) {
|
||||
throw new IllegalArgumentException("Authentication object cannot be null");
|
||||
}
|
||||
this.authentication = authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasAuthority(String authority) {
|
||||
throw new RuntimeException("method hasAuthority() not allowed");
|
||||
}
|
||||
|
||||
//
|
||||
public boolean isMember(Long OrganizationId) {
|
||||
final User user = ((MyUserPrincipal) this.getPrincipal()).getUser();
|
||||
return user.getOrganization().getId().longValue() == OrganizationId.longValue();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public final boolean hasAnyAuthority(String... authorities) {
|
||||
return hasAnyAuthorityName(null, authorities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasRole(String role) {
|
||||
return hasAnyRole(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean hasAnyRole(String... roles) {
|
||||
return hasAnyAuthorityName(defaultRolePrefix, roles);
|
||||
}
|
||||
|
||||
private boolean hasAnyAuthorityName(String prefix, String... roles) {
|
||||
final Set<String> roleSet = getAuthoritySet();
|
||||
|
||||
for (final String role : roles) {
|
||||
final String defaultedRole = getRoleWithDefaultPrefix(prefix, role);
|
||||
if (roleSet.contains(defaultedRole)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Authentication getAuthentication() {
|
||||
return authentication;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean permitAll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean denyAll() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAnonymous() {
|
||||
return trustResolver.isAnonymous(authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAuthenticated() {
|
||||
return !isAnonymous();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isRememberMe() {
|
||||
return trustResolver.isRememberMe(authentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isFullyAuthenticated() {
|
||||
return !trustResolver.isAnonymous(authentication) && !trustResolver.isRememberMe(authentication);
|
||||
}
|
||||
|
||||
public Object getPrincipal() {
|
||||
return authentication.getPrincipal();
|
||||
}
|
||||
|
||||
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
|
||||
this.trustResolver = trustResolver;
|
||||
}
|
||||
|
||||
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
|
||||
this.roleHierarchy = roleHierarchy;
|
||||
}
|
||||
|
||||
public void setDefaultRolePrefix(String defaultRolePrefix) {
|
||||
this.defaultRolePrefix = defaultRolePrefix;
|
||||
}
|
||||
|
||||
private Set<String> getAuthoritySet() {
|
||||
if (roles == null) {
|
||||
roles = new HashSet<String>();
|
||||
Collection<? extends GrantedAuthority> userAuthorities = authentication.getAuthorities();
|
||||
|
||||
if (roleHierarchy != null) {
|
||||
userAuthorities = roleHierarchy.getReachableGrantedAuthorities(userAuthorities);
|
||||
}
|
||||
|
||||
roles = AuthorityUtils.authorityListToSet(userAuthorities);
|
||||
}
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Object target, Object permission) {
|
||||
return permissionEvaluator.hasPermission(authentication, target, permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Object targetId, String targetType, Object permission) {
|
||||
return permissionEvaluator.hasPermission(authentication, (Serializable) targetId, targetType, permission);
|
||||
}
|
||||
|
||||
public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
|
||||
this.permissionEvaluator = permissionEvaluator;
|
||||
}
|
||||
|
||||
private static String getRoleWithDefaultPrefix(String defaultRolePrefix, String role) {
|
||||
if (role == null) {
|
||||
return role;
|
||||
}
|
||||
if ((defaultRolePrefix == null) || (defaultRolePrefix.length() == 0)) {
|
||||
return role;
|
||||
}
|
||||
if (role.startsWith(defaultRolePrefix)) {
|
||||
return role;
|
||||
}
|
||||
return defaultRolePrefix + role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getFilterObject() {
|
||||
return this.filterObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getReturnObject() {
|
||||
return this.returnObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getThis() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFilterObject(Object obj) {
|
||||
this.filterObject = obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReturnObject(Object obj) {
|
||||
this.returnObject = obj;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package org.baeldung.security;
|
||||
|
||||
import org.baeldung.persistence.dao.UserRepository;
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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;
|
||||
|
||||
@Service
|
||||
public class MyUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
public MyUserDetailsService() {
|
||||
super();
|
||||
}
|
||||
|
||||
// API
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(final String username) {
|
||||
final User user = userRepository.findByUsername(username);
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException(username);
|
||||
}
|
||||
return new MyUserPrincipal(user);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package org.baeldung.security;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.baeldung.persistence.model.Privilege;
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
public class MyUserPrincipal implements UserDetails {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final User user;
|
||||
|
||||
//
|
||||
|
||||
public MyUserPrincipal(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return user.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
final List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
|
||||
for (final Privilege privilege : user.getPrivileges()) {
|
||||
authorities.add(new SimpleGrantedAuthority(privilege.getName()));
|
||||
}
|
||||
return authorities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.baeldung.voter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.ConfigAttribute;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
public class MinuteBasedVoter implements AccessDecisionVoter {
|
||||
@Override
|
||||
public boolean supports(ConfigAttribute attribute) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class clazz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int vote(Authentication authentication, Object object, Collection collection) {
|
||||
return authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).filter(r -> "ROLE_USER".equals(r) && LocalDateTime.now().getMinute() % 2 != 0).findAny().map(s -> ACCESS_DENIED).orElseGet(() -> ACCESS_ABSTAIN);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.baeldung.voter;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan(basePackages = { "org.baeldung.voter" })
|
||||
public class VoterApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(VoterApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package org.baeldung.voter;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
/**
|
||||
* Created by ambrusadrianz on 30/09/2016.
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
public class VoterMvcConfig extends WebMvcConfigurerAdapter {
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("private");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.baeldung.voter;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.access.AccessDecisionManager;
|
||||
import org.springframework.security.access.AccessDecisionVoter;
|
||||
import org.springframework.security.access.vote.AuthenticatedVoter;
|
||||
import org.springframework.security.access.vote.RoleVoter;
|
||||
import org.springframework.security.access.vote.UnanimousBased;
|
||||
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;
|
||||
import org.springframework.security.web.access.expression.WebExpressionVoter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
//@Configuration
|
||||
//@EnableWebSecurity
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter: off
|
||||
auth.inMemoryAuthentication().withUser("user").password("pass").roles("USER").and().withUser("admin").password("pass").roles("ADMIN");
|
||||
// @formatter: on
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter: off
|
||||
http
|
||||
// needed so our login could work
|
||||
.csrf().disable().authorizeRequests().anyRequest().authenticated().accessDecisionManager(accessDecisionManager()).antMatchers("/").hasAnyRole("ROLE_ADMIN", "ROLE_USER").and().formLogin().permitAll().and().logout().permitAll()
|
||||
.deleteCookies("JSESSIONID").logoutSuccessUrl("/login");
|
||||
// @formatter: on
|
||||
}
|
||||
|
||||
@Bean
|
||||
public AccessDecisionManager accessDecisionManager() {
|
||||
// @formatter: off
|
||||
List<AccessDecisionVoter<? extends Object>> decisionVoters = Arrays.asList(new WebExpressionVoter(), new RoleVoter(), new AuthenticatedVoter(), new MinuteBasedVoter());
|
||||
// @formatter: on
|
||||
return new UnanimousBased(decisionVoters);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.baeldung.voter;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ImportResource;
|
||||
|
||||
/**
|
||||
* Created by ambrusadrianz on 09/10/2016.
|
||||
*/
|
||||
@Configuration
|
||||
@ImportResource({ "classpath:spring-security.xml" })
|
||||
public class XmlSecurityConfig {
|
||||
public XmlSecurityConfig() {
|
||||
super();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package org.baeldung.web;
|
||||
|
||||
import org.baeldung.persistence.dao.OrganizationRepository;
|
||||
import org.baeldung.persistence.model.Foo;
|
||||
import org.baeldung.persistence.model.Organization;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@Controller
|
||||
public class MainController {
|
||||
|
||||
@Autowired
|
||||
private OrganizationRepository organizationRepository;
|
||||
|
||||
// @PostAuthorize("hasPermission(returnObject, 'read')")
|
||||
@PreAuthorize("hasPermission(#id, 'Foo', 'read')")
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/foos/{id}")
|
||||
@ResponseBody
|
||||
public Foo findById(@PathVariable final long id) {
|
||||
return new Foo("Sample");
|
||||
}
|
||||
|
||||
@PreAuthorize("hasPermission(#foo, 'write')")
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/foos")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ResponseBody
|
||||
public Foo create(@RequestBody final Foo foo) {
|
||||
return foo;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@PreAuthorize("hasAuthority('FOO_READ_PRIVILEGE')")
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/foos")
|
||||
@ResponseBody
|
||||
public Foo findFooByName(@RequestParam final String name) {
|
||||
return new Foo(name);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@PreAuthorize("isMember(#id)")
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/organizations/{id}")
|
||||
@ResponseBody
|
||||
public Organization findOrgById(@PathVariable final long id) {
|
||||
return organizationRepository.findOne(id);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
server.port=8082
|
||||
server.context-path=/spring-security-mvc-boot
|
||||
spring.datasource.driver-class-name=org.h2.Driver
|
||||
spring.datasource.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
spring.datasource.username=sa
|
||||
spring.datasource.password=
|
||||
spring.jpa.hibernate.ddl-auto=create-drop
|
||||
spring.jpa.database=H2
|
||||
spring.jpa.show-sql=false
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
|
|
@ -0,0 +1,12 @@
|
|||
# jdbc.X
|
||||
jdbc.driverClassName=org.apache.derby.jdbc.EmbeddedDriver
|
||||
jdbc.url=jdbc:derby:memory:spring_custom_user_service;create=true
|
||||
jdbc.user=tutorialuser
|
||||
jdbc.pass=tutorialpass
|
||||
|
||||
# hibernate.X
|
||||
hibernate.dialect=org.hibernate.dialect.DerbyDialect
|
||||
hibernate.show_sql=false
|
||||
hibernate.hbm2ddl.auto=create
|
||||
hibernate.cache.use_second_level_cache=false
|
||||
hibernate.cache.use_query_cache=false
|
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/security"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security
|
||||
http://www.springframework.org/schema/security/spring-security-4.2.xsd
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true" auto-config="true" access-decision-manager-ref="accessDecisionManager">
|
||||
<intercept-url pattern="/**" access="hasAnyRole('ROLE_ADMIN', 'ROLE_USER')"/>
|
||||
|
||||
<form-login default-target-url="/"/>
|
||||
<csrf disabled="true"/>
|
||||
<logout logout-url="/logout" delete-cookies="JSESSIONID" logout-success-url="/login"/>
|
||||
</http>
|
||||
|
||||
<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased">
|
||||
<beans:constructor-arg>
|
||||
<beans:list>
|
||||
<beans:bean class="org.springframework.security.web.access.expression.WebExpressionVoter"/>
|
||||
<beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter"/>
|
||||
<beans:bean class="org.springframework.security.access.vote.RoleVoter"/>
|
||||
<beans:bean class="org.baeldung.voter.MinuteBasedVoter"/>
|
||||
</beans:list>
|
||||
</beans:constructor-arg>
|
||||
</beans:bean>
|
||||
|
||||
<beans:bean id="minuteBasedVoter" class="org.baeldung.voter.MinuteBasedVoter"/>
|
||||
|
||||
<authentication-manager>
|
||||
<authentication-provider>
|
||||
<user-service>
|
||||
<user name="user" password="pass" authorities="ROLE_USER"/>
|
||||
<user name="admin" password="pass" authorities="ROLE_ADMIN"/>
|
||||
</user-service>
|
||||
</authentication-provider>
|
||||
</authentication-manager>
|
||||
</beans:beans>
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
You do not have permission to view this page.
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||
<title>Insert title here</title>
|
||||
</head>
|
||||
<body>
|
||||
Welcome admin! <a th:href="@{/admin_logout}" >Logout</a>
|
||||
|
||||
<br /><br />
|
||||
<a th:href="@{/protectedLinks}" >Back to links</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Spring Security Thymeleaf</title>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">Spring Security Thymeleaf</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container">
|
||||
Welcome
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<html>
|
||||
<head></head>
|
||||
|
||||
<body>
|
||||
<h1>Login</h1>
|
||||
|
||||
<form name='f' action="login" method='POST'>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>User:</td>
|
||||
<td><input type="text" name="username"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td><input type="password" name="password" /></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><input name="submit" type="submit" value="submit" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||
<title>Insert title here</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>Admin login page</p>
|
||||
<form name="f" action="admin_login" method="POST">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>User:</td>
|
||||
<td><input type="text" name="username" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td><input type="password" name="password" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input name="submit" type="submit" value="submit" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
<p th:if="${param.error}">Login failed!</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||
<title>Login</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<p>User login page</p>
|
||||
|
||||
<form name="f" action="user_login" method="POST">
|
||||
<table>
|
||||
<tr>
|
||||
<td>User:</td>
|
||||
<td><input type="text" name="username" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td><input type="password" name="password" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input name="submit" type="submit" value="submit" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
<p th:if="${param.error}">Login failed!</p>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
|
||||
<head>
|
||||
<title>Private</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Congrats!</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||
<title>Insert title here</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a th:href="@{/userPage}">User page</a>
|
||||
<br />
|
||||
<a th:href="@{/adminPage}">Admin page</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||
<title>Insert title here</title>
|
||||
</head>
|
||||
<body>
|
||||
Welcome user! <a th:href="@{/user_logout}" >Logout</a>
|
||||
<br /><br />
|
||||
<a th:href="@{/protectedLinks}" >Back to links</a>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,76 @@
|
|||
package org.baeldung.web;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.baeldung.config.MvcConfig;
|
||||
import org.baeldung.config.PersistenceConfig;
|
||||
import org.baeldung.config.SecurityConfig;
|
||||
import org.baeldung.persistence.dao.UserRepository;
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = { MvcConfig.class, SecurityConfig.class, PersistenceConfig.class })
|
||||
@WebAppConfiguration
|
||||
public class CustomUserDetailsServiceIntegrationTest {
|
||||
|
||||
public static final String USERNAME = "user";
|
||||
public static final String PASSWORD = "pass";
|
||||
public static final String USERNAME2 = "user2";
|
||||
|
||||
@Autowired
|
||||
UserRepository myUserRepository;
|
||||
|
||||
@Autowired
|
||||
AuthenticationProvider authenticationProvider;
|
||||
|
||||
@Autowired
|
||||
PasswordEncoder passwordEncoder;
|
||||
|
||||
//
|
||||
|
||||
@Test
|
||||
public void givenExistingUser_whenAuthenticate_thenRetrieveFromDb() {
|
||||
User user = new User();
|
||||
user.setUsername(USERNAME);
|
||||
user.setPassword(passwordEncoder.encode(PASSWORD));
|
||||
|
||||
myUserRepository.save(user);
|
||||
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(USERNAME, PASSWORD);
|
||||
Authentication authentication = authenticationProvider.authenticate(auth);
|
||||
|
||||
assertEquals(authentication.getName(), USERNAME);
|
||||
}
|
||||
|
||||
@Test(expected = BadCredentialsException.class)
|
||||
public void givenIncorrectUser_whenAuthenticate_thenBadCredentialsException() {
|
||||
User user = new User();
|
||||
user.setUsername(USERNAME);
|
||||
user.setPassword(passwordEncoder.encode(PASSWORD));
|
||||
|
||||
myUserRepository.save(user);
|
||||
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(USERNAME2, PASSWORD);
|
||||
authenticationProvider.authenticate(auth);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
myUserRepository.removeUserByUsername(USERNAME);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package org.baeldung.web;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.baeldung.persistence.model.Foo;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import com.jayway.restassured.RestAssured;
|
||||
import com.jayway.restassured.authentication.FormAuthConfig;
|
||||
import com.jayway.restassured.response.Response;
|
||||
import com.jayway.restassured.specification.RequestSpecification;
|
||||
|
||||
public class LiveTest {
|
||||
|
||||
private final FormAuthConfig formAuthConfig = new FormAuthConfig("http://localhost:8082/spring-security-custom-permission/login", "username", "password");
|
||||
|
||||
@Test
|
||||
public void givenUserWithReadPrivilegeAndHasPermission_whenGetFooById_thenOK() {
|
||||
final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/foos/1");
|
||||
assertEquals(200, response.getStatusCode());
|
||||
assertTrue(response.asString().contains("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUserWithNoWritePrivilegeAndHasPermission_whenPostFoo_thenForbidden() {
|
||||
final Response response = givenAuth("john", "123").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8082/spring-security-custom-permission/foos");
|
||||
assertEquals(403, response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUserWithWritePrivilegeAndHasPermission_whenPostFoo_thenOk() {
|
||||
final Response response = givenAuth("tom", "111").contentType(MediaType.APPLICATION_JSON_VALUE).body(new Foo("sample")).post("http://localhost:8082/spring-security-custom-permission/foos");
|
||||
assertEquals(201, response.getStatusCode());
|
||||
assertTrue(response.asString().contains("id"));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Test
|
||||
public void givenUserMemberInOrganization_whenGetOrganization_thenOK() {
|
||||
final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/organizations/1");
|
||||
assertEquals(200, response.getStatusCode());
|
||||
assertTrue(response.asString().contains("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUserMemberNotInOrganization_whenGetOrganization_thenForbidden() {
|
||||
final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/organizations/2");
|
||||
assertEquals(403, response.getStatusCode());
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@Test
|
||||
public void givenDisabledSecurityExpression_whenGetFooByName_thenError() {
|
||||
final Response response = givenAuth("john", "123").get("http://localhost:8082/spring-security-custom-permission/foos?name=sample");
|
||||
assertEquals(500, response.getStatusCode());
|
||||
assertTrue(response.asString().contains("method hasAuthority() not allowed"));
|
||||
}
|
||||
|
||||
//
|
||||
private RequestSpecification givenAuth(String username, String password) {
|
||||
return RestAssured.given().auth().form(username, password, formAuthConfig);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue