From 0badc0f83d9cf33aac7f3bcddd32fca37fd0ae8c Mon Sep 17 00:00:00 2001 From: flykhan Date: Mon, 20 Feb 2023 22:15:52 +0800 Subject: [PATCH] =?UTF-8?q?Login=20+=20getInfo=20+=20Register=20=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=20API=20=E4=B9=A6=E5=86=99,=20login=20+=20logout=20?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=B9=A6=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/pom.xml | 30 ++++++ .../kob/backend/config/SecurityConfig.java | 42 +++++++- .../filter/JwtAuthenticationTokenFilter.java | 68 ++++++++++++ .../controller/user/UserController.java | 5 +- .../user/account/InfoController.java | 20 ++++ .../user/account/LoginController.java | 27 +++++ .../user/account/RegisterController.java | 24 +++++ .../main/java/com/kob/backend/pojo/User.java | 7 +- .../service/impl/UserDetailsServiceImpl.java | 6 ++ .../impl/user/account/InfoServiceImpl.java | 34 ++++++ .../impl/user/account/LoginServiceImpl.java | 50 +++++++++ .../user/account/RegisterServiceImpl.java | 81 ++++++++++++++ .../service/user/account/InfoService.java | 8 ++ .../service/user/account/LoginService.java | 8 ++ .../service/user/account/RegisterService.java | 9 ++ .../java/com/kob/backend/utils/JwtUtil.java | 74 +++++++++++++ web/src/App.vue | 47 ++++++++ web/src/components/NavBar.vue | 42 +++++++- web/src/router/index.js | 12 +++ web/src/store/index.js | 3 + web/src/store/user.js | 100 ++++++++++++++++++ .../user/account/UserAccountLoginView.vue | 98 +++++++++++++++++ .../user/account/UserAccountRegisterView.vue | 15 +++ 23 files changed, 802 insertions(+), 8 deletions(-) create mode 100644 backend/src/main/java/com/kob/backend/config/filter/JwtAuthenticationTokenFilter.java create mode 100644 backend/src/main/java/com/kob/backend/controller/user/account/InfoController.java create mode 100644 backend/src/main/java/com/kob/backend/controller/user/account/LoginController.java create mode 100644 backend/src/main/java/com/kob/backend/controller/user/account/RegisterController.java create mode 100644 backend/src/main/java/com/kob/backend/service/impl/user/account/InfoServiceImpl.java create mode 100644 backend/src/main/java/com/kob/backend/service/impl/user/account/LoginServiceImpl.java create mode 100644 backend/src/main/java/com/kob/backend/service/impl/user/account/RegisterServiceImpl.java create mode 100644 backend/src/main/java/com/kob/backend/service/user/account/InfoService.java create mode 100644 backend/src/main/java/com/kob/backend/service/user/account/LoginService.java create mode 100644 backend/src/main/java/com/kob/backend/service/user/account/RegisterService.java create mode 100644 backend/src/main/java/com/kob/backend/utils/JwtUtil.java create mode 100644 web/src/store/user.js create mode 100644 web/src/views/user/account/UserAccountLoginView.vue create mode 100644 web/src/views/user/account/UserAccountRegisterView.vue diff --git a/backend/pom.xml b/backend/pom.xml index e7d4e58..3e8ff70 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -68,6 +68,30 @@ 3.0.2 + + + + io.jsonwebtoken + jjwt-api + 0.11.5 + + + + + io.jsonwebtoken + jjwt-impl + 0.11.5 + runtime + + + + + io.jsonwebtoken + jjwt-jackson + 0.11.5 + runtime + + org.springframework.boot @@ -83,6 +107,12 @@ spring-boot-starter-test test + + org.jetbrains + annotations + 13.0 + compile + diff --git a/backend/src/main/java/com/kob/backend/config/SecurityConfig.java b/backend/src/main/java/com/kob/backend/config/SecurityConfig.java index 935eed9..c31d787 100644 --- a/backend/src/main/java/com/kob/backend/config/SecurityConfig.java +++ b/backend/src/main/java/com/kob/backend/config/SecurityConfig.java @@ -1,17 +1,55 @@ package com.kob.backend.config; +/* +主要作用:放行登录、注册等接口 +*/ + +import com.kob.backend.config.filter.JwtAuthenticationTokenFilter; +import org.springframework.beans.factory.annotation.Autowired; 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.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.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; -//明文加密 +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +// TODO: 2023/2/19 WebSecurityConfigurerAdapter 已被弃用,注意替换 @Configuration @EnableWebSecurity -public class SecurityConfig { +public class SecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired + private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; +// 配置密码加密方式 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } +/* + .antMatchers("/user/account/token/", "/user/account/register/").permitAll() + 用于配置公开链接 +*/ + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) + .and() + .authorizeRequests() + .antMatchers("/user/account/token/", "/user/account/register/").permitAll() + .antMatchers(HttpMethod.OPTIONS).permitAll() + .anyRequest().authenticated(); + + http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + } } \ No newline at end of file diff --git a/backend/src/main/java/com/kob/backend/config/filter/JwtAuthenticationTokenFilter.java b/backend/src/main/java/com/kob/backend/config/filter/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..605b038 --- /dev/null +++ b/backend/src/main/java/com/kob/backend/config/filter/JwtAuthenticationTokenFilter.java @@ -0,0 +1,68 @@ +package com.kob.backend.config.filter; + +//filter 类用于验证 +/* +主要作用: + 1. 用来验证jwt token,如果验证成功,则将User信息注入上下文中 +*/ + +import com.kob.backend.mapper.UserMapper; +import com.kob.backend.pojo.User; +import com.kob.backend.service.impl.utils.UserDetailsImpl; +import com.kob.backend.utils.JwtUtil; +import com.sun.xml.internal.bind.v2.TODO; +import io.jsonwebtoken.Claims; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + @Autowired + private UserMapper userMapper; + + @Override + protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException { + String token = request.getHeader("Authorization"); + +// TODO 这里可以更改 bearar 为其他字符作为验证前缀 + if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) { + filterChain.doFilter(request, response); + return; + } + + token = token.substring(7); + + String userid; + try { + Claims claims = JwtUtil.parseJWT(token); + userid = claims.getSubject(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + User user = userMapper.selectById(Integer.parseInt(userid)); + + if (user == null) { + throw new RuntimeException("用户名未登录"); + } + + UserDetailsImpl loginUser = new UserDetailsImpl(user); + UsernamePasswordAuthenticationToken authenticationToken = + new UsernamePasswordAuthenticationToken(loginUser, null, null); + + SecurityContextHolder.getContext().setAuthentication(authenticationToken); + + filterChain.doFilter(request, response); + } +} \ No newline at end of file diff --git a/backend/src/main/java/com/kob/backend/controller/user/UserController.java b/backend/src/main/java/com/kob/backend/controller/user/UserController.java index 78610a1..7339fb4 100644 --- a/backend/src/main/java/com/kob/backend/controller/user/UserController.java +++ b/backend/src/main/java/com/kob/backend/controller/user/UserController.java @@ -12,7 +12,8 @@ import org.springframework.web.bind.annotation.RestController; import java.util.List; -//实现对用户类 User 的增删查操作 +//实现对用户类 User 的增删查操作->这个类仅用于调试,故 Deparecated 掉 +@Deprecated @RestController public class UserController { @@ -58,7 +59,7 @@ public class UserController { // 加密明文密码并存入密文到数据库 PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encodedPassword = passwordEncoder.encode(password); - User user = new User(userId, username, encodedPassword); + User user = new User(userId, username, encodedPassword,""); userMapper.insert(user); return "Add User Successfully"; } diff --git a/backend/src/main/java/com/kob/backend/controller/user/account/InfoController.java b/backend/src/main/java/com/kob/backend/controller/user/account/InfoController.java new file mode 100644 index 0000000..e41cc7b --- /dev/null +++ b/backend/src/main/java/com/kob/backend/controller/user/account/InfoController.java @@ -0,0 +1,20 @@ +package com.kob.backend.controller.user.account; + +import com.kob.backend.service.user.account.InfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@RestController +public class InfoController { + @Autowired + private InfoService infoService; + +// 获取信息 + @GetMapping("/user/account/info/") + public Map getInfo(){ + return infoService.getInfo(); + } +} diff --git a/backend/src/main/java/com/kob/backend/controller/user/account/LoginController.java b/backend/src/main/java/com/kob/backend/controller/user/account/LoginController.java new file mode 100644 index 0000000..60acf37 --- /dev/null +++ b/backend/src/main/java/com/kob/backend/controller/user/account/LoginController.java @@ -0,0 +1,27 @@ +package com.kob.backend.controller.user.account; + +import com.kob.backend.service.user.account.LoginService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +//@RestController 配合 @PostMapping("/.../.../") 使用:映射 Url 地址 +@RestController +public class LoginController { +// @Autowired 注入接口 + @Autowired + private LoginService loginService; + +// 登录使用 POST 请求,密文传输,更安全 + @PostMapping("/user/account/token/") + public Map getToken(@RequestParam Map map){ + String username = map.get("username"); + String password = map.get("password"); + + return loginService.getToken(username,password); + } + +} diff --git a/backend/src/main/java/com/kob/backend/controller/user/account/RegisterController.java b/backend/src/main/java/com/kob/backend/controller/user/account/RegisterController.java new file mode 100644 index 0000000..1ecf8dc --- /dev/null +++ b/backend/src/main/java/com/kob/backend/controller/user/account/RegisterController.java @@ -0,0 +1,24 @@ +package com.kob.backend.controller.user.account; + +import com.kob.backend.service.user.account.RegisterService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@RestController +public class RegisterController { + @Autowired + private RegisterService registerService; + + @PostMapping("/user/account/register/") + public Map register(@RequestParam Map map) { + String username = map.get("username"); + String password = map.get("password"); + String confirmedPassword = map.get("confirmedPassword"); + return registerService.register(username, password, confirmedPassword); + } + +} diff --git a/backend/src/main/java/com/kob/backend/pojo/User.java b/backend/src/main/java/com/kob/backend/pojo/User.java index 5db506e..a037e15 100644 --- a/backend/src/main/java/com/kob/backend/pojo/User.java +++ b/backend/src/main/java/com/kob/backend/pojo/User.java @@ -6,6 +6,8 @@ Data 用于编译时自动生成 getter setter 方法; NoArgsConstructor 用于生成无参构造函数; AllArgsConstructor 用于生成所有参数构造函数. */ +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,9 +17,12 @@ import lombok.NoArgsConstructor; @AllArgsConstructor public class User { - // 使用对象类型定义而不是 Int 防止 Mybatis 报错 +// 使用对象类型定义而不是 Int 防止 Mybatis 报错 +// @TableId(type = IdType.AUTO) 用于 id 的自增 + @TableId(type = IdType.AUTO) private Integer id; private String username; private String password; + private String photo; } diff --git a/backend/src/main/java/com/kob/backend/service/impl/UserDetailsServiceImpl.java b/backend/src/main/java/com/kob/backend/service/impl/UserDetailsServiceImpl.java index 8bd7d9f..223512a 100644 --- a/backend/src/main/java/com/kob/backend/service/impl/UserDetailsServiceImpl.java +++ b/backend/src/main/java/com/kob/backend/service/impl/UserDetailsServiceImpl.java @@ -18,6 +18,12 @@ public class UserDetailsServiceImpl implements UserDetailsService { private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { +/* + 从数据库里读取用户信息,比对用户名密码与数据库存在的用户名密码,信息一致,给用户发一个 sessionID , + 存到用户本地浏览器,服务器同时会自己存一份。未来用户再登录时服务器会将自己的 sessionID 与用户发过来 + 请求包含的 sessionID 进行比照,如果一致,则授权成功。 +*/ + QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("username",username); User user = userMapper.selectOne(queryWrapper); diff --git a/backend/src/main/java/com/kob/backend/service/impl/user/account/InfoServiceImpl.java b/backend/src/main/java/com/kob/backend/service/impl/user/account/InfoServiceImpl.java new file mode 100644 index 0000000..119a3d4 --- /dev/null +++ b/backend/src/main/java/com/kob/backend/service/impl/user/account/InfoServiceImpl.java @@ -0,0 +1,34 @@ +package com.kob.backend.service.impl.user.account; + +import com.kob.backend.pojo.User; +import com.kob.backend.service.impl.utils.UserDetailsImpl; +import com.kob.backend.service.user.account.InfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + + +@Service +public class InfoServiceImpl implements InfoService { + @Override + public Map getInfo() { + UsernamePasswordAuthenticationToken authenticationToken = + (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); + + UserDetailsImpl loginUser = (UserDetailsImpl) authenticationToken.getPrincipal(); + User user = loginUser.getUser(); + + Map map = new HashMap<>(); + map.put("error_message","success"); + map.put("id",user.getId().toString()); + map.put("username",user.getUsername()); + map.put("photo",user.getPhoto()); + + + return map; + } +} diff --git a/backend/src/main/java/com/kob/backend/service/impl/user/account/LoginServiceImpl.java b/backend/src/main/java/com/kob/backend/service/impl/user/account/LoginServiceImpl.java new file mode 100644 index 0000000..19071fe --- /dev/null +++ b/backend/src/main/java/com/kob/backend/service/impl/user/account/LoginServiceImpl.java @@ -0,0 +1,50 @@ +package com.kob.backend.service.impl.user.account; + +import com.kob.backend.pojo.User; +import com.kob.backend.service.impl.utils.UserDetailsImpl; +import com.kob.backend.service.user.account.LoginService; +import com.kob.backend.utils.JwtUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; + +//@Service 注解用于注入接口实现到 Spring 里面 +@Service +public class LoginServiceImpl implements LoginService { + +// @Autowired 用于注入 + @Autowired + private AuthenticationManager authenticationManager; + + @Override + public Map getToken(String username, String password) { + +// 封装用户名和密码成 UsernamePasswordAuthenticationToken 类:此类不存储明文,而是存储加密之后的字符串 + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,password); + +// 验证是否正常登录,登录验证失败时会自动处理(报异常) + Authentication authenticate = authenticationManager.authenticate(authenticationToken); +// 登录成功,取出用户 + UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal(); + User user = loginUser.getUser(); + +// 封装 jwt 信息:将 userID 转换为 String + String jwt = JwtUtil.createJWT(user.getId().toString()); + +/* + 成功之后返回结果: + 1. "error_message" 为 success;失败之后会报异常,自动处理掉 + 2. "token" 返回 jwt-token 信息 +*/ + Map map = new HashMap<>(); + map.put("error_message","success"); + map.put("token",jwt); + + return map; + } +} diff --git a/backend/src/main/java/com/kob/backend/service/impl/user/account/RegisterServiceImpl.java b/backend/src/main/java/com/kob/backend/service/impl/user/account/RegisterServiceImpl.java new file mode 100644 index 0000000..9998cab --- /dev/null +++ b/backend/src/main/java/com/kob/backend/service/impl/user/account/RegisterServiceImpl.java @@ -0,0 +1,81 @@ +package com.kob.backend.service.impl.user.account; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.kob.backend.pojo.User; +import com.kob.backend.mapper.UserMapper; +import com.kob.backend.service.user.account.RegisterService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; +import java.util.List; + +@Service +public class RegisterServiceImpl implements RegisterService { + // 这里使用 @Autowired 注入是为了调用数据库,然后进行数据库查询,比较是否有用户名重复 + @Autowired + private UserMapper userMapper; + + @Override + public Map register(String username, String password, String confirmedPassword) { + Map map = new HashMap<>(); +// 如果用户名为空,则提示用户返回 + if (username == null) { + map.put("error_message", "用户名不能为空"); + return map; + } + if (password == null || confirmedPassword == null) { + map.put("error_message", "密码不能为空"); + return map; + } +// 用户名需要将输入的首尾空格删掉 + username = username.trim(); + if (username.length() == 0) { + map.put("error_message", "用户名不能为空"); + return map; + } + if (password.length() == 0) { + map.put("error_message", "密码不能为空"); + return map; + } + if (username.length() > 100) { + map.put("error_message", "用户名过长"); + return map; + } + if (password.length() > 100 || confirmedPassword.length() > 100) { + map.put("error_message", "密码过长"); + return map; + } +// 密码验证是 String 类型比较,应该用 equals() 方法 + if (!confirmedPassword.equals(password)) { + map.put("error_message", "两次密码输入不一致"); + return map; + } + +/* + 查询数据库里是否有用户名 this.username 已存在的用户,并将结果存入 users 中, + 如果发现 users 不是空的,则告诉注册用户当前用户名已存在 +*/ + QueryWrapper queryWrapper = new QueryWrapper(); + queryWrapper.eq("username", username); + List users = userMapper.selectList(queryWrapper); + if (!users.isEmpty()) { + map.put("error_message", "用户名已存在"); + return map; + } + +// 异常情况判断结束,开始将合法用户注册信息注入数据库 +// 对密码进行加密 + String encodedPassword = new BCryptPasswordEncoder().encode(password); +// 默认头像 + String photo = "https://cdn.acwing.com/media/user/profile/photo/253652_lg_e3d8435b66.jpg"; +// id 是数据库自增,这里生成新用户只需要将 id 参数写为 null 即可 + User user = new User(null,username,encodedPassword,photo); + userMapper.insert(user); + + map.put("error_message","成功注册"); + return map; + } +} diff --git a/backend/src/main/java/com/kob/backend/service/user/account/InfoService.java b/backend/src/main/java/com/kob/backend/service/user/account/InfoService.java new file mode 100644 index 0000000..9826259 --- /dev/null +++ b/backend/src/main/java/com/kob/backend/service/user/account/InfoService.java @@ -0,0 +1,8 @@ +package com.kob.backend.service.user.account; + +import java.util.Map; + +//根据令牌返回用户信息 +public interface InfoService { + public Map getInfo(); +} diff --git a/backend/src/main/java/com/kob/backend/service/user/account/LoginService.java b/backend/src/main/java/com/kob/backend/service/user/account/LoginService.java new file mode 100644 index 0000000..16b813c --- /dev/null +++ b/backend/src/main/java/com/kob/backend/service/user/account/LoginService.java @@ -0,0 +1,8 @@ +package com.kob.backend.service.user.account; + +import java.util.Map; + +//验证用户名密码,验证成功后返回jwt token(令牌) +public interface LoginService { + public Map getToken(String username, String password); +} diff --git a/backend/src/main/java/com/kob/backend/service/user/account/RegisterService.java b/backend/src/main/java/com/kob/backend/service/user/account/RegisterService.java new file mode 100644 index 0000000..5e59592 --- /dev/null +++ b/backend/src/main/java/com/kob/backend/service/user/account/RegisterService.java @@ -0,0 +1,9 @@ +package com.kob.backend.service.user.account; + +import java.util.Map; + +//注册账号 +public interface RegisterService { +// confirmedPassword 密码确认 + public Map register(String username, String password, String confirmedPassword); +} diff --git a/backend/src/main/java/com/kob/backend/utils/JwtUtil.java b/backend/src/main/java/com/kob/backend/utils/JwtUtil.java new file mode 100644 index 0000000..b23d22b --- /dev/null +++ b/backend/src/main/java/com/kob/backend/utils/JwtUtil.java @@ -0,0 +1,74 @@ +package com.kob.backend.utils; + +//jwt工具类,用来创建、解析 jwt token +/* +主要作用: + 1. 将字符串加上密钥,加上有效期,转换为加密后的字符串; + 2. 给一个令牌,将其 userID 解析出来. + +依赖:添加到 pom.xml 中,然后使用 Maven 重新加载依赖项 + jjwt-apt; + jjwt-impl; + jjwt-jackson. +*/ + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtBuilder; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import java.util.Base64; +import java.util.Date; +import java.util.UUID; + +@Component +public class JwtUtil { + public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14; // 有效期14天:单位-毫秒 ms + public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232113afasdfad"; // 密钥:随机字符串-大小写英文字母+数字 + + public static String getUUID() { + return UUID.randomUUID().toString().replaceAll("-", ""); + } + + public static String createJWT(String subject) { + JwtBuilder builder = getJwtBuilder(subject, null, getUUID()); + return builder.compact(); + } + + private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) { + SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; + SecretKey secretKey = generalKey(); + long nowMillis = System.currentTimeMillis(); + Date now = new Date(nowMillis); + if (ttlMillis == null) { + ttlMillis = JwtUtil.JWT_TTL; + } + + long expMillis = nowMillis + ttlMillis; + Date expDate = new Date(expMillis); + return Jwts.builder() + .setId(uuid) + .setSubject(subject) + .setIssuer("sg") + .setIssuedAt(now) + .signWith(signatureAlgorithm, secretKey) + .setExpiration(expDate); + } + + public static SecretKey generalKey() { + byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY); + return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256"); + } + + public static Claims parseJWT(String jwt) throws Exception { + SecretKey secretKey = generalKey(); + return Jwts.parserBuilder() + .setSigningKey(secretKey) + .build() + .parseClaimsJws(jwt) + .getBody(); + } +} \ No newline at end of file diff --git a/web/src/App.vue b/web/src/App.vue index 6aabd64..f62dacb 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -10,9 +10,56 @@ import NavBar from "./components/NavBar.vue"; // 导入 BootStrap 的 css 和 js 依赖以同步 BootStrap 样式 import "bootstrap/dist/css/bootstrap.css"; import "bootstrap/dist/js/bootstrap"; +// import $ from "jquery"; export default { components: { NavBar }, + /* setup: () => { + $.ajax({ + url: "http://localhost:3000/user/account/token/", + type: "POST", + data: { + username: "bb", + password: "pbb", + }, + success(resp) { + console.log(resp.token, "\n成功了\n", resp.error_message); + }, + error(resp) { + console.log(resp); + }, + }); + $.ajax({ + url: "http://localhost:3000/user/account/info/", + type: "GET", + headers: { + Authorization: + "Bearer " + + "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIzODA2Yzc0ODkwYTE0NTgwYjcyOGQzOWI4NDYyYWY2ZSIsInN1YiI6IjYiLCJpc3MiOiJzZyIsImlhdCI6MTY3Njg4ODk5MywiZXhwIjoxNjc4MDk4NTkzfQ.mq7Xdt3G7VGvX7fgIYGN2MfH8bo9MuZ7V0nfzGmbDZ8", + }, + success(resp) { + console.log(resp); + }, + error(resp) { + console.log(resp); + }, + }); + $.ajax({ + url: "http://localhost:3000/user/account/register/", + type: "POST", + data: { + username: "cc", + password: "pcc", + confirmedPassword: "pcc", + }, + success(resp) { + console.log(resp); + }, + error(resp) { + console.log(resp); + }, + }); + }, */ }; diff --git a/web/src/views/user/account/UserAccountRegisterView.vue b/web/src/views/user/account/UserAccountRegisterView.vue new file mode 100644 index 0000000..1fc4de7 --- /dev/null +++ b/web/src/views/user/account/UserAccountRegisterView.vue @@ -0,0 +1,15 @@ + + + + +