本文将重点介绍使用 Spring Boot 的 Spring Security 与 JPA 和 MySQL 数据库的身份验证过程。通过 Spring Data JPA 对数据库中的用户信息进行身份验证是一个简单的过程。
正如之前通过 JDBC 进行 Spring Security 身份验证中所分享的那样,希望您对 Spring Security 有一些基本的了解。
让我们来看看 Spring Security 是如何管理认证的:
您将构建 3 个 REST 服务,该服务将在以下位置接受 HTTP GET
请求:
1- http://localhost:8080/admin
2- http://localhost:8080/user
3- http://localhost:8080/all
并分别以问候的 HTML 表示形式响应:
1- Welcome Admin!
2- Welcome User!
3- Hello Everyone!
但在访问上述服务之前,用户必须使用存储在 MySQL 数据库中的凭据进行身份验证:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
并从数据库中获取用户信息,覆盖 Spring Security 本身提供的 UserDetailsService
接口的 loadUserByUsername(String *userName*)
方法。
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
Optional<User> user = userRepository.findByUserName(userName);
user.orElseThrow(() -> new UsernameNotFoundException(userName + " not found."));
return user.map(UserDetailsImpl::new).get();
}
认证成功后,用户必须具有有效的权限/角色才能访问服务:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin").hasRole(ADMIN)
.antMatchers("/user").hasAnyRole(ADMIN,USER)
.antMatchers("/all").permitAll()
.and().formLogin();
}
###你需要什么
约 30 分钟
最喜欢的文本编辑器或 IDE
JDK 1.8 或更高版本
Gradle 4+ 或 Maven 3.2+
MySQL 数据库
您也可以将代码直接导入您的 IDE:
弹簧工具套件 (STS)
日食
IntelliJ IDEA
要使用 Spring Data JPA 和 Spring Security,请将以下依赖项添加到 pom.xml。
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<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>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
我们在 STS 4 IDE 中的应用程序的最终项目结构如下所示:
MyController
类为应用程序用户公开 REST 端点。在这个控制器类中,我们创建了 3 个不同的 REST 端点,如下所示:
我的控制器
package org.websparrow.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/admin")
public String admin() {
return "<h2>Welcome Admin!</h2>";
}
@GetMapping("/user")
public String user() {
return "<h2>Welcome User!</h2>";
}
@GetMapping("/all")
public String all() {
return "<h2>Hello Everyone!</h2>";
}
}
User
类是一个实体类,代表user 表结构并保存所有必要的用户信息。
用户.java
package org.websparrow.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String userName;
private String password;
private boolean isActive;
private String roles;
// Generate Getters and Setters...
}
UserRepository
接口用于查询数据库和获取用户信息。为此,您必须创建一个派生的 findBy 查询方法 findByUserName(String *userName*)
。
UserRepository.java
package org.websparrow.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import org.websparrow.entity.User;
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUserName(String userName);
}
UserDetailsServiceImpl
是 Spring Framework 提供的 UserDetailsService
接口的实现类。您必须覆盖其 loadUserByUsername(String *userName*)
方法,该方法返回 UserDetails
接口的实例。
UserDetailsServiceImpl.java
package org.websparrow.service;
import java.util.Optional;
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;
import org.websparrow.entity.User;
import org.websparrow.repository.UserRepository;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
Optional<User> user = userRepository.findByUserName(userName);
user.orElseThrow(() -> new UsernameNotFoundException(userName + " not found."));
return user.map(UserDetailsImpl::new).get();
}
}
UserDetailsImpl
类实现了 UserDetails
接口来保存所有用户信息。
UserDetailsImpl.java
package org.websparrow.service;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.websparrow.entity.User;
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;
private String userName;
private String password;
private boolean isActive;
private List<GrantedAuthority> authorities;
public UserDetailsImpl(User user) {
this.userName = user.getUserName();
this.password = user.getPassword();
this.isActive = user.isActive();
this.authorities = Arrays.stream(user.getRoles().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
public UserDetailsImpl() {}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return userName;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return isActive;
}
}
创建一个扩展 WebSecurityConfigurerAdapter
的 Spring Security 配置类。通过添加 @EnableWebSecurity
,您可以获得 Spring Security 支持。覆盖其 configure(AuthenticationManagerBuilder *auth*)
方法并调用 [ [$19$]] 类的 userDetailsService()
方法,传递 UserDetailsService
对象,其余部分将由 Spring Security 自动管理。
SecurityConfiguration.java
package org.websparrow.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String ADMIN = "ADMIN";
private static final String USER = "USER";
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin").hasRole(ADMIN)
.antMatchers("/user").hasAnyRole(ADMIN, USER)
.antMatchers("/all").permitAll()
.and().formLogin();
}
@Bean
public PasswordEncoder getPasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
}
记住
1.不要在生产中使用NoOpPasswordEncoder
来编码密码。我们仅用于演示目的。
3.你可以随时更改身份验证,无论你是使用JDBC、文本文件、硬编码值等。这就是Spring Security框架的美妙之处。
在 application.properties 文件中配置数据库连接字符串,以建立应用程序和数据库之间的连接。
application.properties
# MySQL database connection strings
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=root
# JPA property settings
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true
BootSecurityJpaApp
类包含主要方法并负责启动应用程序。
BootSecurityJpaApp.java
package org.websparrow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class BootSecurityJpaApp {
public static void main(String[] args) {
SpringApplication.run(BootSecurityJpaApp.class, args);
}
}
要测试应用程序,请通过执行上述类来启动 Spring Boot 应用程序,并按照以下步骤操作:
加载用户信息:
insert into `user`(`id`,`is_active`,`password`,`roles`,`user_name`)
values (1,1,'user@123','ROLE_USER','user'),
(2,1,'admin@123','ROLE_ADMIN','admin');
对于 /admin 页面:
对于/用户页面:
对于/所有页面:
恭喜!您刚刚使用 Spring Boot 使用 MySQL 数据库开发了 Spring Security JPA 身份验证。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.websparrow.org/spring/spring-boot-spring-security-with-jpa-authentication-and-mysql
内容来源于网络,如有侵权,请联系作者删除!