TEST #1

Merged
p6m75oc2z merged 14 commits from TEST into main 2 weeks ago

@ -1,5 +1,5 @@
# Maven
target/
./target
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup

@ -49,4 +49,9 @@ public class SecurityConfig {
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public org.springframework.security.crypto.password.PasswordEncoder passwordEncoder() {
return new org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder();
}
}

@ -0,0 +1,56 @@
package com.studyingspace.controller;
import com.studyingspace.common.Result;
import com.studyingspace.dto.LoginRequest;
import com.studyingspace.dto.LoginResponse;
import com.studyingspace.dto.RegisterRequest;
import com.studyingspace.entity.User;
import com.studyingspace.repository.UserRepository;
import com.studyingspace.utils.JwtUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/auth")
@Tag(name = "用户认证", description = "登录注册接口")
@RequiredArgsConstructor
public class AuthController {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final JwtUtils jwtUtils;
@PostMapping("/register")
@Operation(summary = "用户注册", description = "注册新用户")
public Result<String> register(@RequestBody RegisterRequest request) {
if (userRepository.existsByUsername(request.getUsername())) {
return Result.error("用户名已存在");
}
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(passwordEncoder.encode(request.getPassword()));
userRepository.save(user);
return Result.success("注册成功");
}
@PostMapping("/login")
@Operation(summary = "用户登录", description = "登录并返回 JWT token")
public Result<LoginResponse> login(@RequestBody LoginRequest request) {
User user = userRepository.findByUsername(request.getUsername()).orElse(null);
if (user == null) {
return Result.error(401, "用户名不存在");
}
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
return Result.error(401, "密码错误");
}
String token = jwtUtils.generateToken(user.getUsername());
return Result.success(new LoginResponse(token, user.getUsername()));
}
}

@ -16,5 +16,6 @@ public class HelloController {
@Operation(summary = "欢迎接口", description = "返回欢迎信息")
public Result<String> hello() {
return Result.success("Hello StudyingSpace!");
}
}

@ -0,0 +1,9 @@
package com.studyingspace.dto;
import lombok.Data;
@Data
public class LoginRequest {
private String username;
private String password;
}

@ -0,0 +1,14 @@
package com.studyingspace.dto;
import lombok.Data;
@Data
public class LoginResponse {
private String token;
private String username;
public LoginResponse(String token, String username) {
this.token = token;
this.username = username;
}
}

@ -0,0 +1,9 @@
package com.studyingspace.dto;
import lombok.Data;
@Data
public class RegisterRequest {
private String username;
private String password;
}

@ -0,0 +1,36 @@
package com.studyingspace.entity;
import jakarta.persistence.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password;
private LocalDateTime createTime;
private LocalDateTime updateTime;
@PrePersist
protected void onCreate() {
createTime = LocalDateTime.now();
updateTime = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updateTime = LocalDateTime.now();
}
}

@ -0,0 +1,11 @@
package com.studyingspace.repository;
import com.studyingspace.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
boolean existsByUsername(String username);
}

@ -0,0 +1,60 @@
package com.studyingspace.utils;
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.Component;
import java.security.Key;
import java.util.Date;
import java.nio.charset.StandardCharsets;
@Component
public class JwtUtils {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
private Key getSigningKey() {
return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
}
public String generateToken(String username) {
Date now = new Date();
Date expiryDate = new Date(now.getTime() + expiration);
return Jwts.builder()
.setSubject(username)
.setIssuedAt(now)
.setExpiration(expiryDate)
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();
}
public String getUsernameFromToken(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public boolean validateToken(String token) {
try {
Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token);
return true;
} catch (Exception e) {
return false;
}
}
}

@ -4,7 +4,7 @@ server:
spring:
application:
name: studyingspace-backend
#数据库账号密码
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/StudyingSystem

@ -11,7 +11,8 @@
"vue": "^3.4.0",
"vue-router": "^4.2.5",
"pinia": "^2.1.7",
"axios": "^1.6.2"
"axios": "^1.6.2",
"element-plus": "^2.4.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.5.2",

@ -0,0 +1,17 @@
import request from '@/utils/request'
export function login(data) {
return request({
url: '/auth/login',
method: 'post',
data
})
}
export function register(data) {
return request({
url: '/auth/register',
method: 'post',
data
})
}

@ -2,11 +2,14 @@ import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import './styles/main.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')

@ -21,6 +21,8 @@
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { login } from '../../api/auth'
import { ElMessage } from 'element-plus'
const router = useRouter()
const form = ref({
@ -28,8 +30,21 @@ const form = ref({
password: ''
})
const handleLogin = () => {
console.log('login', form.value)
const handleLogin = async () => {
try {
const res = await login(form.value)
if (res.code === 200) {
localStorage.setItem('token', res.data.token)
localStorage.setItem('username', res.data.username)
ElMessage.success('登录成功')
router.push('/')
} else {
ElMessage.error(res.message)
}
} catch (error) {
ElMessage.error('登录失败')
console.error(error)
}
}
const goRegister = () => {

@ -24,6 +24,8 @@
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { register } from '../../api/auth'
import { ElMessage } from 'element-plus'
const router = useRouter()
const form = ref({
@ -32,8 +34,30 @@ const form = ref({
confirmPassword: ''
})
const handleRegister = () => {
console.log('register', form.value)
const handleRegister = async () => {
if (!form.value.username || !form.value.password) {
ElMessage.warning('请填写用户名和密码')
return
}
if (form.value.password !== form.value.confirmPassword) {
ElMessage.warning('两次输入的密码不一致')
return
}
try {
const res = await register({
username: form.value.username,
password: form.value.password
})
if (res.code === 200) {
ElMessage.success('注册成功,请登录')
router.push('/login')
} else {
ElMessage.error(res.message)
}
} catch (error) {
ElMessage.error('注册失败')
console.error(error)
}
}
const goLogin = () => {

@ -1,8 +1,14 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
server: {
proxy: {
'/api': {

Loading…
Cancel
Save