在 Spring Boot 中创建 RESTful API 接口,实现用户登录和注册功能。
时间: 2024-04-29 07:21:22 浏览: 9
好的,以下是一个简单的示例:
首先,创建一个 Spring Boot 项目,并添加以下依赖:
```xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<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>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
<scope>runtime</scope>
</dependency>
</dependencies>
```
其中,`spring-boot-starter-web` 用于创建 web 项目,`spring-boot-starter-data-jpa` 用于访问数据库,`spring-boot-starter-security` 用于实现安全认证,`jjwt` 用于生成和验证 JWT Token,`h2` 用于创建内存数据库。
接下来,创建一个 User 实体类:
```java
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
@Transient
private String confirmPassword;
// getter 和 setter 省略
}
```
该实体类包含 id、username 和 password 三个字段,其中 username 是唯一的,password 会在存储时进行加密处理,confirmPassword 字段在注册时用于确认密码,不会被存储。
接着,创建 UserRepository 接口:
```java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
```
该接口继承了 JpaRepository 接口,用于访问 User 实体类对应的表。其中,`findByUsername` 方法用于通过 username 查找 User 对象。
然后,创建一个 JwtUtil 工具类:
```java
@Component
public class JwtUtil {
private String SECRET_KEY = "secret";
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
Date now = new Date();
Date expirationDate = new Date(now.getTime() + 3600000);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(now)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
private boolean isTokenExpired(String token) {
final Date expiration = extractExpiration(token);
return expiration.before(new Date());
}
private Date extractExpiration(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration();
}
private String extractUsername(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();
}
}
```
该工具类用于生成和验证 JWT Token。其中,`generateToken` 方法用于生成 Token,`validateToken` 方法用于验证 Token 是否有效。
接下来,创建一个 AuthService 接口:
```java
public interface AuthService {
User register(User user);
String login(String username, String password);
}
```
该接口定义了注册和登录两个方法。
然后,创建一个 AuthServiceImpl 实现类:
```java
@Service
public class AuthServiceImpl implements AuthService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserRepository userRepository;
@Autowired
private JwtUtil jwtUtil;
@Override
public User register(User user) {
String encodedPassword = new BCryptPasswordEncoder().encode(user.getPassword());
user.setPassword(encodedPassword);
return userRepository.save(user);
}
@Override
public String login(String username, String password) {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (Exception e) {
throw new RuntimeException("Invalid username or password");
}
final UserDetails userDetails = new User(userRepository.findByUsername(username).getUsername(), userRepository.findByUsername(username).getPassword(), new ArrayList<>());
return jwtUtil.generateToken(userDetails);
}
}
```
该实现类中,`register` 方法用于注册用户,将密码进行加密处理后保存到数据库中;`login` 方法用于登录,通过验证用户名和密码后生成 Token 并返回。
最后,创建一个 UserController 类:
```java
@RestController
@RequestMapping("/api")
public class UserController {
@Autowired
private AuthService authService;
@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody User user) {
authService.register(user);
return ResponseEntity.ok("User registered successfully");
}
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody Map<String, String> loginData) {
String username = loginData.get("username");
String password = loginData.get("password");
String token = authService.login(username, password);
return ResponseEntity.ok(token);
}
}
```
该类中,`register` 方法用于注册用户,接受一个 User 对象作为参数;`login` 方法用于登录,接受一个包含用户名和密码的 Map 对象作为参数。
现在,启动应用程序,并使用 Postman 或其他工具测试接口。可以使用 `/api/register` 接口注册用户,使用 `/api/login` 接口登录,并将返回的 Token 作为请求头中的 Authorization 参数访问其他受保护的接口。