custom expression handler
This commit is contained in:
parent
c879a9dc74
commit
8892b7bc65
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="optional" value="true"/>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
|
<attributes>
|
||||||
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
||||||
|
</attributes>
|
||||||
|
</classpathentry>
|
||||||
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
|
</classpath>
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>spring-security-custom-permission</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||||
|
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
|
||||||
|
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
|
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||||
|
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -0,0 +1,107 @@
|
||||||
|
<?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-custom-permission</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<name>spring-security-custom-permission</name>
|
||||||
|
<description>Spring Security custom permission</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>1.3.3.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>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>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<rest-assured.version>2.4.0</rest-assured.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.baeldung;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
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,43 @@
|
||||||
|
package org.baeldung.config;
|
||||||
|
|
||||||
|
import org.baeldung.security.MyUserDetailsService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
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.RoleRepository;
|
||||||
|
import org.baeldung.persistence.dao.UserRepository;
|
||||||
|
import org.baeldung.persistence.model.Organization;
|
||||||
|
import org.baeldung.persistence.model.Privilege;
|
||||||
|
import org.baeldung.persistence.model.Role;
|
||||||
|
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 RoleRepository roleRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PrivilegeRepository privilegeRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OrganizationRepository organizationRepository;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
initPrivileges();
|
||||||
|
initRoles();
|
||||||
|
initOrganizations();
|
||||||
|
initUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUsers() {
|
||||||
|
final Role role1 = roleRepository.findByName("USER_ROLE");
|
||||||
|
final Role role2 = roleRepository.findByName("ADMIN_ROLE");
|
||||||
|
//
|
||||||
|
final User user1 = new User();
|
||||||
|
user1.setUsername("john");
|
||||||
|
user1.setPassword("123");
|
||||||
|
user1.setRoles(new HashSet<Role>(Arrays.asList(role1)));
|
||||||
|
user1.setOrganization(organizationRepository.findByName("FirstOrg"));
|
||||||
|
userRepository.save(user1);
|
||||||
|
//
|
||||||
|
final User user2 = new User();
|
||||||
|
user2.setUsername("tom");
|
||||||
|
user2.setPassword("111");
|
||||||
|
user2.setRoles(new HashSet<Role>(Arrays.asList(role2)));
|
||||||
|
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 initRoles() {
|
||||||
|
final Privilege privilege1 = privilegeRepository.findByName("FOO_READ_PRIVILEGE");
|
||||||
|
final Privilege privilege2 = privilegeRepository.findByName("FOO_WRITE_PRIVILEGE");
|
||||||
|
//
|
||||||
|
final Role role1 = new Role("USER_ROLE");
|
||||||
|
role1.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1)));
|
||||||
|
roleRepository.save(role1);
|
||||||
|
//
|
||||||
|
final Role role2 = new Role("ADMIN_ROLE");
|
||||||
|
role2.setPrivileges(new HashSet<Privilege>(Arrays.asList(privilege1, privilege2)));
|
||||||
|
roleRepository.save(role2);
|
||||||
|
}
|
||||||
|
|
||||||
|
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,9 @@
|
||||||
|
package org.baeldung.persistence.dao;
|
||||||
|
|
||||||
|
import org.baeldung.persistence.model.Role;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface RoleRepository extends JpaRepository<Role, Long> {
|
||||||
|
public Role findByName(String name);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.baeldung.persistence.dao;
|
||||||
|
|
||||||
|
import org.baeldung.persistence.model.User;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
|
||||||
|
User findByUsername(final 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,121 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Role {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
|
@JoinTable(name = "roles_privileges", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id"))
|
||||||
|
private Set<Privilege> privileges;
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
public Role() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Role(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Privilege> getPrivileges() {
|
||||||
|
return privileges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivileges(Set<Privilege> privileges) {
|
||||||
|
this.privileges = privileges;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
final StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("Role [id=").append(id).append(", name=").append(name).append(", privileges=").append(privileges).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());
|
||||||
|
result = (prime * result) + ((privileges == null) ? 0 : privileges.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 Role other = (Role) 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;
|
||||||
|
}
|
||||||
|
if (privileges == null) {
|
||||||
|
if (other.privileges != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!privileges.equals(other.privileges)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
package org.baeldung.persistence.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
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 org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class User implements UserDetails {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@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_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
|
||||||
|
private Set<Role> roles;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Role> getRoles() {
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoles(Set<Role> roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(", roles=").append(roles).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) + ((roles == null) ? 0 : roles.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 (roles == null) {
|
||||||
|
if (other.roles != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!roles.equals(other.roles)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (username == null) {
|
||||||
|
if (other.username != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!username.equals(other.username)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
final List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
|
||||||
|
for (final Role role : this.getRoles()) {
|
||||||
|
for (final Privilege privilege : role.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 = (User) this.getPrincipal();
|
||||||
|
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,47 @@
|
||||||
|
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) {
|
||||||
|
System.out.println(auth);
|
||||||
|
if ((auth == null) || (targetDomainObject == null) || !(permission instanceof String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
String targetType = "";
|
||||||
|
if (targetDomainObject instanceof String) {
|
||||||
|
targetType = targetDomainObject.toString().toUpperCase();
|
||||||
|
} else {
|
||||||
|
targetType = targetDomainObject.getClass().getSimpleName().toUpperCase();
|
||||||
|
System.out.println(targetType);
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
public boolean isMember(Long OrganizationId) {
|
||||||
|
final User user = (User) this.getPrincipal();
|
||||||
|
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,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 user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
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;
|
||||||
|
|
||||||
|
@PreAuthorize("hasPermission('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,9 @@
|
||||||
|
server.port=8081
|
||||||
|
spring.datasource.driver-class-name=org.h2.Driver
|
||||||
|
spring.datasource.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1
|
||||||
|
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,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,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:8081/login", "username", "password");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenUserWithReadPrivilegeAndHasPermission_whenGetFooById_thenOK() {
|
||||||
|
final Response response = givenAuth("john", "123").get("http://localhost:8081/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:8081/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:8081/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:8081/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:8081/organizations/2");
|
||||||
|
assertEquals(403, response.getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenDisabledSecurityExpression_whenGetFooByName_thenError() {
|
||||||
|
final Response response = givenAuth("john", "123").get("http://localhost:8081/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