For learning about Spring Data Jpa, you can refer to: One article is enough to learn Spring Data JPA
Article Directory
One, create a project
Note that in addition to Spring Security dependencies, we also need data dependencies and Spring Data Jpa dependencies.
After the project is created, we then create an empty library in the database, called jpa, without doing anything in it, so that our preparatory work is completed.
Two, prepare the model
(1) Role entity class:
@Entity(name = "t_role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String nameZh;
//省略 getter/setter
}
This entity class is used to describe user role information. It has role id and role name (English, Chinese), @Entity
indicating that this is an entity class. After the project is started, a role table will be automatically created in the database based on the attributes of the entity class.
(2) User entity class
@Entity(name = "t_user")
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
private boolean accountNonExpired;
private boolean accountNonLocked;
private boolean credentialsNonExpired;
private boolean enabled;
@ManyToMany(fetch = FetchType.EAGER,cascade = CascadeType.PERSIST)
private List<Role> roles;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for (Role role : getRoles()) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return accountNonExpired;
}
@Override
public boolean isAccountNonLocked() {
return accountNonLocked;
}
@Override
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
@Override
public boolean isEnabled() {
return enabled;
}
//省略其他 get/set 方法
}
User entity principal need to implement UserDetails
the interface, and implementation of the interface method.
The fields here are basically easy to understand, let me talk about a few special ones:
(1)
accountNonExpired
,accountNonLocked
,credentialsNonExpired
,enabled
four attributes are used to describe the state of the user, indicating whether the account has not expired, whether the account is not locked, whether the password has not expired, and the account is available.
(2) roles attribute represents the user's role, User, and Role-many relationship with an@ManyToMany
annotation described.
(3) The getAuthorities method returns the user's role information. In this method, we can transform our Role a little bit.
Three, configuration
After the data model is ready, let's define a UserDao:
public interface UserDao extends JpaRepository<User,Long> {
User findUserByUsername(String username);
}
Here's something very simple, we only need to inherit JpaRepository
and to provide a method according to the user's query username.
Define UserService next, as follows:
@Service
public class UserService implements UserDetailsService {
@Autowired
UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userDao.findUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在");
}
return user;
}
}
Our own definition of UserService
the need to achieve UserDetailsService
interface, this interface, the interface methods must achieve, that is, loadUserByUsername
after the parameter of this method is that when users log incoming user name, user name to query user information (check out , The system will automatically compare the passwords).
After the configuration is complete, let's do a little configuration in Spring Security. I still use Spring Security and HelloController used for testing from the previous article, mainly listing the places that need to be modified.
In SecurityConfig, we configure users in the following ways:
@Autowired
UserService userService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
Please note that we are still rewriting the configure method, but this time we are not based on memory, nor based on it JdbcUserDetailsManager
, but using a custom one UserService
, so the configuration is OK.
Finally, we configure the basic information of the database and JPA in application.properties, as follows:
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.jpa.database=mysql
spring.jpa.database-platform=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
Four, test
First, let's add test data, add the following method to the unit test:
@Test
void contextLoads() {
User user = new User();
user.setUsername("yolo");
user.setPassword("123");
user.setAccountNonExpired(true);
user.setAccountNonLocked(true);
user.setCredentialsNonExpired(true);
user.setEnabled(true);
List<Role> list = new ArrayList<>();
Role role = new Role();
role.setName("ROLE_admin");
role.setNameZh("管理员");
list.add(role);
user.setRoles(list);
userDao.save(user);
}
After a successful login, access respectively /hello,/admin/hello
and /user/hello
three interfaces, including:
(1)
/hello
Because you can access after logging in, this interface is successfully accessed.
(2) The/admin/hello
admin identity is required, so the access fails.
(3) The/user/hello
user identity is required, so the access is successful.