1
1
.
.
4
4
.
.
9
9
A
A
u
u
t
t
h
h
o
o
r
r
i
i
t
t
i
i
e
e
s
s
-
-
D
D
B
B
I
I
n
n
f
f
o
o
[
[
G
G
]
]
This tutorial shows how to get User's Authorities from the DB by grouping them into Profiles.
By assigning Profile to Account, Account is given Authorities that are related to that Profile.
Application Schema [Results]
DB Schema (Profile & Authority have ManyToMany Relationship)
MyController
http://localhost:8080/ReadBook
Tomcat
readBook()
Browser
Authority
AuthorityRepository
MyUserDetails
Service
Profile
ProfileRepository
Account
AccountRepository
ID
ACCOUNT
PROFILE
USERNAME
PASSWORD
NAME
PROFILE
NAME
AUTHORITY
1 : X
PROFILE_NAME
PROFILE_AUTHORITIES
AUTHORITIES_NAME
ACCOUNT (Loaded Data)
ID
USERNAME
PASSWORD
PROFILE
1
admin
adminpassword
ADMIN
2
user
userpassword
USER
PROFILE
NAME
ADMIN
USER
PROFILE_AUTHORITIES
PROFILE_NAME
AUTHORITIES_NAME
ADMIN
book.create
ADMIN
book.delete
ADMIN
book.read
ADMIN
book.update
USER
book.read
AUTHORITY
NAME
book.create
book.delete
book.read
book.update
Spring Boot Starters
GROUP
DEPENDENCY
DESCRIPTION
Web
Spring Web
Enables: @Controller, @RequestMapping, Tomcat Server
Security
Spring Security
Enables: Spring Security
SQL
Spring Data JPA
Enables: @Entity, @Id
SQL
H2 Database
Enables: in-memory H2 Database
O
O
v
v
e
e
r
r
v
v
i
i
e
e
w
w
The main part of this tutorial is @Service class AccountService implements UserDetailsService { .. }.
It @Overrides loadUserByUsername(String username) which is automatically called by Login Form with entered username
Inside this method we create User Object with authorities which are related to Profile that is given to Account.
SecurityConfig.java To enable @PreAuthorize
@EnableGlobalMethodSecurity(prePostEnabled = true)
MyController.java CRUD DB Operations
@PreAuthorize("hasAuthority('book.create')")
@PreAuthorize("hasAuthority('book.read')")
@PreAuthorize("hasAuthority('book.update')")
@PreAuthorize("hasAuthority('book.delete')")
P
P
r
r
o
o
c
c
e
e
d
d
u
u
r
r
e
e
Create Project: springboot_security_authorization_authorities_db (add Spring Boot Starters from the table)
Edit File: application.properties (specify Username, Password, Role)
Create Package: entities (inside main package)
– Create Class: Authority.java (inside entities package)
– Create Class: Profile.java (inside entities package)
– Create Class: Account.java (inside entities package)
Create Package: repositories (inside main package)
– Create Class: AuthorityRepository.java (inside repositories package)
– Create Class: ProfileRepository.java (inside repositories package)
– Create Class: AccountRepository.java (inside repositories package)
Create Package: config (inside main package)
– Create Class: WebSecurityConfig.java (inside config package)
Create Package: startup (inside main package)
– Create Class: AuthorityLoader.java (inside config package)
– Create Class: ProfileLoader.java (inside config package)
– Create Class: AccountLoader.java (inside config package)
Create Package: services (inside main package)
– Create Class: MyUserDetailsService.java (inside services package)
Create Package: controllers (inside main package)
– Create Class: MyController.java (inside controllers package)
application.properties
# H2 CONSOLE
spring.h2.console.enabled = true
spring.datasource.url = jdbc:h2:mem:testdb
Authority.java
package com.ivoronline.springboot_security_authorization_authorities_db.entities;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Authority {
@Id
public String name;
//CONSTRUCTORS
public Authority() { } //Forced by @Entity
public Authority(String name) { this.name = name; } //To simplify AuthorityLoader
}
Profile.java
package com.ivoronline.springboot_security_authorization_authorities_db.entities;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import java.util.HashSet;
import java.util.Set;
@Entity
public class Profile {
@Id
public String name;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "profile")
public Set<Account> account = new HashSet<>();
@ManyToMany(cascade = CascadeType.ALL)
public Set<Authority> authorities = new HashSet<>();
}
Account.java
package com.ivoronline.springboot_security_authorization_authorities_db.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer id;
public String username;
public String password;
//FOREIGN KEY
public String profile;
}
AuthorityRepository.java
package com.ivoronline.springboot_security_authorization_authorities_db.repositories;
import com.ivoronline.springboot_security_authorization_authorities_db.entities.Authority;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AuthorityRepository extends JpaRepository<Authority, String> { }
ProfileRepository.java
package com.ivoronline.springboot_security_authorization_authorities_db.repositories;
import com.ivoronline.springboot_security_authorization_authorities_db.entities.Profile;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ProfileRepository extends JpaRepository<Profile, String> { }
AccountRepository.java
package com.ivoronline.springboot_security_authorization_authorities_db.repositories;
import com.ivoronline.springboot_security_authorization_authorities_db.entities.Account;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AccountRepository extends JpaRepository<Account, Integer> {
Account findByUsername(String Username);
}
AuthorityLoader.java
package com.ivoronline.springboot_security_authorization_authorities_db.startup;
import com.ivoronline.springboot_security_authorization_authorities_db.entities.Authority;
import com.ivoronline.springboot_security_authorization_authorities_db.repositories.AuthorityRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Order(1)
@Component
public class AuthorityLoader implements CommandLineRunner {
@Autowired private AuthorityRepository authorityRepository;
@Override
@Transactional
public void run(String... args) throws Exception {
authorityRepository.save(new Authority("book.create"));
authorityRepository.save(new Authority("book.read"));
authorityRepository.save(new Authority("book.update"));
authorityRepository.save(new Authority("book.delete"));
}
}
ProfileLoader.java
package com.ivoronline.springboot_security_authorization_authorities_db.startup;
import com.ivoronline.springboot_security_authorization_authorities_db.entities.Authority;
import com.ivoronline.springboot_security_authorization_authorities_db.entities.Profile;
import com.ivoronline.springboot_security_authorization_authorities_db.repositories.AuthorityRepository;
import com.ivoronline.springboot_security_authorization_authorities_db.repositories.ProfileRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
@Order(2)
public class ProfileLoader implements CommandLineRunner {
@Autowired private ProfileRepository profileRepository;
@Autowired private AuthorityRepository authorityRepository;
@Override
@Transactional
public void run(String... args) throws Exception {
//GET AUTHORITIES.
Authority bookCreate = authorityRepository.findById("book.create").get();
Authority bookRead = authorityRepository.findById("book.read" ).get();
Authority bookUpdate = authorityRepository.findById("book.update").get();
Authority bookDelete = authorityRepository.findById("book.delete").get();
//USER
Profile user = new Profile();
user.name = "USER";
user.authorities.add(bookRead);
//ADMIN
Profile admin = new Profile();
admin.name = "ADMIN";
admin.authorities.add(bookCreate);
admin.authorities.add(bookRead);
admin.authorities.add(bookUpdate);
admin.authorities.add(bookDelete);
//STORE PROFILES INTO DB
profileRepository.save(user);
profileRepository.save(admin);
}
}
AccountLoader.java
package com.ivoronline.springboot_security_authorization_authorities_db.startup;
import com.ivoronline.springboot_security_authorization_authorities_db.entities.Account;
import com.ivoronline.springboot_security_authorization_authorities_db.repositories.AccountRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Component
@Order(3)
public class AccountLoader implements CommandLineRunner {
@Autowired private AccountRepository accountRepository;
@Override
@Transactional
public void run(String... args) throws Exception {
//ADMIN: ANDREW
Account admin = new Account();
admin.username = "admin";
admin.password = "adminpassword";
admin.profile = "ADMIN";
//USER: URBAN
Account user = new Account();
user.username = "user";
user.password = "userpassword";
user.profile = "USER";
//STORE ACCOUNT INTO DB
accountRepository.save(admin);
accountRepository.save(user);
}
}