mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-04-21 03:17:28 +08:00
Merge pull request #1 from nagisa77/codex/implement-open-source-community-backend
Add initial Spring Boot backend with JWT
This commit is contained in:
63
README.md
63
README.md
@@ -1,2 +1,63 @@
|
|||||||
# OpenIsle
|
# OpenIsle
|
||||||
开源的社区后端平台 Open source community backend platform.
|
|
||||||
|
OpenIsle 是一个基于 Spring Boot 的社区后端平台示例,提供注册、登录和基于 JWT 的认证功能,支持使用 MySQL 作为数据库,并通过 [Resend](https://resend.com) API 发送注册邮件。
|
||||||
|
|
||||||
|
## 功能特性
|
||||||
|
|
||||||
|
- **注册/登录**:用户可以注册并登录,密码使用 BCrypt 加密保存。
|
||||||
|
- **JWT 认证**:登录成功后返回 JWT,后续请求需在 `Authorization` 头中携带 `Bearer` token。
|
||||||
|
- **邮件通知**:示例通过 Resend API 发送欢迎邮件,可根据需要修改。
|
||||||
|
- **灵活配置**:数据库地址、账户密码、Resend API Key 等均可通过环境变量或 `application.properties` 配置。
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### 环境准备
|
||||||
|
|
||||||
|
- Java 17+
|
||||||
|
- Maven 3+
|
||||||
|
- MySQL 数据库
|
||||||
|
|
||||||
|
### 构建与运行
|
||||||
|
|
||||||
|
1. 修改 `src/main/resources/application.properties`,或通过环境变量配置:
|
||||||
|
- `MYSQL_URL`:数据库连接 URL,例如 `jdbc:mysql://localhost:3306/openisle`。
|
||||||
|
- `MYSQL_USER`:数据库用户名。
|
||||||
|
- `MYSQL_PASSWORD`:数据库密码。
|
||||||
|
- `RESEND_API_KEY`:Resend 邮件服务 API Key。
|
||||||
|
- `JWT_SECRET`:JWT 签名密钥。
|
||||||
|
- `JWT_EXPIRATION`:JWT 过期时间(毫秒)。
|
||||||
|
|
||||||
|
2. 构建并运行:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
启动后访问:
|
||||||
|
|
||||||
|
- `POST /api/auth/register`:注册新用户,参数示例:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"username": "test",
|
||||||
|
"email": "test@example.com",
|
||||||
|
"password": "password"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- `POST /api/auth/login`:登录,返回 `{ "token": "..." }`。
|
||||||
|
- 其他受保护接口示例:`GET /api/hello`,需在请求头加入 `Authorization: Bearer <token>`。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
src/main/java/com/openisle
|
||||||
|
├── OpenIsleApplication.java // 应用入口
|
||||||
|
├── config // Spring Security 配置
|
||||||
|
├── controller // 控制器
|
||||||
|
├── model // 数据模型
|
||||||
|
├── repository // 数据访问层
|
||||||
|
└── service // 业务逻辑
|
||||||
|
```
|
||||||
|
|
||||||
|
## 许可
|
||||||
|
|
||||||
|
本项目使用 MIT License,可自由修改和分发。
|
||||||
|
|||||||
74
pom.xml
Normal file
74
pom.xml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<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.openisle</groupId>
|
||||||
|
<artifactId>openisle</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>OpenIsle</name>
|
||||||
|
<description>Open source community backend platform</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<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>com.mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-j</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-api</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-impl</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt-jackson</artifactId>
|
||||||
|
<version>0.11.5</version>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
11
src/main/java/com/openisle/OpenIsleApplication.java
Normal file
11
src/main/java/com/openisle/OpenIsleApplication.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package com.openisle;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class OpenIsleApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(OpenIsleApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
92
src/main/java/com/openisle/config/SecurityConfig.java
Normal file
92
src/main/java/com/openisle/config/SecurityConfig.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package com.openisle.config;
|
||||||
|
|
||||||
|
import com.openisle.service.JwtService;
|
||||||
|
import com.openisle.repository.UserRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SecurityConfig {
|
||||||
|
private final JwtService jwtService;
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserDetailsService userDetailsService() {
|
||||||
|
return username -> userRepository.findByUsername(username)
|
||||||
|
.<UserDetails>map(user -> org.springframework.security.core.userdetails.User
|
||||||
|
.withUsername(user.getUsername())
|
||||||
|
.password(user.getPassword())
|
||||||
|
.authorities("USER")
|
||||||
|
.build())
|
||||||
|
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public AuthenticationManager authenticationManager(HttpSecurity http, PasswordEncoder passwordEncoder, UserDetailsService userDetailsService) throws Exception {
|
||||||
|
return http.getSharedObject(AuthenticationManagerBuilder.class)
|
||||||
|
.userDetailsService(userDetailsService)
|
||||||
|
.passwordEncoder(passwordEncoder)
|
||||||
|
.and()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
http.csrf(csrf -> csrf.disable())
|
||||||
|
.sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||||
|
.authorizeHttpRequests(auth -> auth
|
||||||
|
.requestMatchers(HttpMethod.POST, "/api/auth/**").permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
)
|
||||||
|
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public OncePerRequestFilter jwtAuthenticationFilter() {
|
||||||
|
return new OncePerRequestFilter() {
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
String authHeader = request.getHeader("Authorization");
|
||||||
|
if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
||||||
|
String token = authHeader.substring(7);
|
||||||
|
try {
|
||||||
|
String username = jwtService.validateAndGetSubject(token);
|
||||||
|
UserDetails userDetails = userDetailsService().loadUserByUsername(username);
|
||||||
|
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||||
|
org.springframework.security.core.context.SecurityContextHolder.getContext().setAuthentication(authToken);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/main/java/com/openisle/controller/AuthController.java
Normal file
52
src/main/java/com/openisle/controller/AuthController.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package com.openisle.controller;
|
||||||
|
|
||||||
|
import com.openisle.model.User;
|
||||||
|
import com.openisle.service.EmailService;
|
||||||
|
import com.openisle.service.JwtService;
|
||||||
|
import com.openisle.service.UserService;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/auth")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AuthController {
|
||||||
|
private final UserService userService;
|
||||||
|
private final JwtService jwtService;
|
||||||
|
private final EmailService emailService;
|
||||||
|
|
||||||
|
@PostMapping("/register")
|
||||||
|
public ResponseEntity<?> register(@RequestBody RegisterRequest req) {
|
||||||
|
User user = userService.register(req.getUsername(), req.getEmail(), req.getPassword());
|
||||||
|
emailService.sendEmail(user.getEmail(), "Welcome to OpenIsle", "Thank you for registering.");
|
||||||
|
String token = jwtService.generateToken(user.getUsername());
|
||||||
|
return ResponseEntity.ok(new JwtResponse(token));
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/login")
|
||||||
|
public ResponseEntity<?> login(@RequestBody LoginRequest req) {
|
||||||
|
return userService.authenticate(req.getUsername(), req.getPassword())
|
||||||
|
.map(user -> ResponseEntity.ok(new JwtResponse(jwtService.generateToken(user.getUsername()))))
|
||||||
|
.orElse(ResponseEntity.status(401).build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
private static class RegisterRequest {
|
||||||
|
private String username;
|
||||||
|
private String email;
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
private static class LoginRequest {
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
private static class JwtResponse {
|
||||||
|
private final String token;
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/main/java/com/openisle/controller/HelloController.java
Normal file
12
src/main/java/com/openisle/controller/HelloController.java
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package com.openisle.controller;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HelloController {
|
||||||
|
@GetMapping("/api/hello")
|
||||||
|
public String hello() {
|
||||||
|
return "Hello, Authenticated User";
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/java/com/openisle/model/User.java
Normal file
26
src/main/java/com/openisle/model/User.java
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package com.openisle.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Table(name = "users")
|
||||||
|
public class User {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String password;
|
||||||
|
}
|
||||||
10
src/main/java/com/openisle/repository/UserRepository.java
Normal file
10
src/main/java/com/openisle/repository/UserRepository.java
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package com.openisle.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import com.openisle.model.User;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
Optional<User> findByUsername(String username);
|
||||||
|
Optional<User> findByEmail(String email);
|
||||||
|
}
|
||||||
38
src/main/java/com/openisle/service/EmailService.java
Normal file
38
src/main/java/com/openisle/service/EmailService.java
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package com.openisle.service;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.http.HttpEntity;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class EmailService {
|
||||||
|
|
||||||
|
@Value("${resend.api.key}")
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate = new RestTemplate();
|
||||||
|
|
||||||
|
public void sendEmail(String to, String subject, String text) {
|
||||||
|
String url = "https://api.resend.com/emails"; // hypothetical endpoint
|
||||||
|
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
headers.set("Authorization", "Bearer " + apiKey);
|
||||||
|
|
||||||
|
Map<String, String> body = new HashMap<>();
|
||||||
|
body.put("to", to);
|
||||||
|
body.put("subject", subject);
|
||||||
|
body.put("text", text);
|
||||||
|
body.put("from", "demo@openisle.example");
|
||||||
|
|
||||||
|
HttpEntity<Map<String, String>> entity = new HttpEntity<>(body, headers);
|
||||||
|
restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/main/java/com/openisle/service/JwtService.java
Normal file
45
src/main/java/com/openisle/service/JwtService.java
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package com.openisle.service;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import io.jsonwebtoken.security.Keys;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.security.Key;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class JwtService {
|
||||||
|
|
||||||
|
@Value("${app.jwt.secret}")
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@Value("${app.jwt.expiration}")
|
||||||
|
private long expiration;
|
||||||
|
|
||||||
|
private Key getSigningKey() {
|
||||||
|
return Keys.hmacShaKeyFor(secret.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String generateToken(String subject) {
|
||||||
|
Date now = new Date();
|
||||||
|
Date expiryDate = new Date(now.getTime() + expiration);
|
||||||
|
return Jwts.builder()
|
||||||
|
.setSubject(subject)
|
||||||
|
.setIssuedAt(now)
|
||||||
|
.setExpiration(expiryDate)
|
||||||
|
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
|
||||||
|
.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String validateAndGetSubject(String token) {
|
||||||
|
Claims claims = Jwts.parserBuilder()
|
||||||
|
.setSigningKey(getSigningKey())
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(token)
|
||||||
|
.getBody();
|
||||||
|
return claims.getSubject();
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/main/java/com/openisle/service/UserService.java
Normal file
33
src/main/java/com/openisle/service/UserService.java
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package com.openisle.service;
|
||||||
|
|
||||||
|
import com.openisle.model.User;
|
||||||
|
import com.openisle.repository.UserRepository;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class UserService {
|
||||||
|
private final UserRepository userRepository;
|
||||||
|
private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||||
|
|
||||||
|
public User register(String username, String email, String password) {
|
||||||
|
if (userRepository.findByUsername(username).isPresent() || userRepository.findByEmail(email).isPresent()) {
|
||||||
|
throw new RuntimeException("User already exists");
|
||||||
|
}
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername(username);
|
||||||
|
user.setEmail(email);
|
||||||
|
user.setPassword(passwordEncoder.encode(password));
|
||||||
|
return userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<User> authenticate(String username, String password) {
|
||||||
|
return userRepository.findByUsername(username)
|
||||||
|
.filter(user -> passwordEncoder.matches(password, user.getPassword()));
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/main/resources/application.properties
Normal file
9
src/main/resources/application.properties
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
spring.datasource.url=${MYSQL_URL:jdbc:mysql://localhost:3306/openisle}
|
||||||
|
spring.datasource.username=${MYSQL_USER:root}
|
||||||
|
spring.datasource.password=${MYSQL_PASSWORD:password}
|
||||||
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
|
|
||||||
|
resend.api.key=${RESEND_API_KEY:}
|
||||||
|
|
||||||
|
app.jwt.secret=${JWT_SECRET:ChangeThisSecretKeyForJwt}
|
||||||
|
app.jwt.expiration=${JWT_EXPIRATION:86400000}
|
||||||
Reference in New Issue
Block a user