【Java闭关修炼】SpringBoot项目-贪吃蛇对战小游戏-配置Mysql与注册登录模块2
创始人
2025-05-30 18:49:41
0

【Java闭关修炼】SpringBoot项目-贪吃蛇对战小游戏-配置Mysql与注册登录模块2

    • 传统的登录验证模式
    • JWT登录验证方式
    • 下载安装依赖
    • 创建JWTUTIL
    • JwtAuthenticationTokenFilter的创建
    • config.SecurityConfig的创建
    • 将用户表格设置成自增ID
    • 在数据库创建新的列
    • 在Pojo.user类中添加注解
    • 实现/user/account/token/
      • 创建LoginService接口
      • 创建RegisterService接口
      • 创建InfoService的接口
      • 实现LoginServiceImpl接口
    • 实现LoginController
    • 实现InfoServiceImpl
    • 实现InfoController
    • 实现RegisterServiceImpl
    • 实现RegisterController
    • 前端页面的实现

传统的登录验证模式

在这里插入图片描述

在这里插入图片描述

用户在登录之后,数据库会比对用户名和密码,然后如果正确的话返回一个sessionID,服务器端存储SESSIONID,然后 访问其他页面的时候,浏览器会判断session是否有效,然后将用户信息提取到上下文,访问controller层。

JWT登录验证方式

在这里插入图片描述

下载安装依赖

  • jjwt-api

  • jjwt-impl

  • jjwt-jackson

添加到pom.xml中

创建JWTUTIL

该类是jwt工具类 用来创建 解析jwt token

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天public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac";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();}
}

JwtAuthenticationTokenFilter的创建

用来验证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 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 {@Autowiredprivate UserMapper userMapper;@Overrideprotected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {String token = request.getHeader("Authorization");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);}
}

config.SecurityConfig的创建

用来放行登录、注册等接口

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;@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected 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);}
}

将用户表格设置成自增ID

在这里插入图片描述

在数据库创建新的列

存储用户头像,数据库存头像 存储的是链接

在这里插入图片描述

将自己的用户头像链接复制到数据库表格中

在这里插入图片描述

在Pojo.user类中添加注解

设置ID自增

package com.kob.backedn2.pojo;// 数据库一张表对应一个类  @data 将常用的get set方法 添加进去
//@NoArgsConstructor  无参构造函数
//@AllArgsConstructor  有参构造函数
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {@TableId(type = IdType.AUTO)private Integer id;private String username;private String password;private String photo;
}

实现/user/account/token/

验证用户名密码 验证成功之后 返回jwt token

创建LoginService接口

package com.kob.backedn2.service.user.account;import java.util.Map;public interface LoginService {//     返回登录信息public Map login(String username, String password);
}

创建RegisterService接口

package com.kob.backedn2.service.user.account;import java.util.Map;public interface RegisterService {public Map register(String username, String password, String confirmedPassword);}

创建InfoService的接口

package com.kob.backedn2.service.user.account;import java.util.Map;public interface InfoService {public Map getInfo();
}

实现LoginServiceImpl接口

package com.kob.backedn2.service.impl.user.account;
import com.kob.backedn2.pojo.User;
import com.kob.backedn2.service.impl.utils.UserDetailsImpl;
import com.kob.backedn2.service.user.account.LoginService;
import com.kob.backedn2.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.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.Map;// 添加注解service
@Service
public class LoginServiceImpl implements LoginService {// 需要用到的东西 都要注入进来  加上注解 autowired@Autowiredprivate AuthenticationManager authenticationManager;@Overridepublic Map login(String username, String password) {UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,password);// 登录失败 会自动处理Authentication authenticate = authenticationManager.authenticate(authenticationToken);// 登录成功 获得一个token对象// 取出用户信息UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal();User user = loginUser.getUser();// 获取用户对象// 创建jwt token对象String jwt  = JwtUtil.createJWT(user.getId().toString());Map map = new HashMap<>();map.put("error_message","success");map.put("token",jwt);return map;}
}

实现LoginController

该类主要用来根据用户名和密码获取token

package com.kob.backedn2.controller.user.account;
import com.kob.backedn2.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
public class LoginController {//     注入service的接口@Autowiredprivate LoginService loginService;// 登录是post请求  将该链接公开化@PostMapping("/user/account/token/")public Map getToken(@RequestParam Map map){String username = map.get("username");String password = map.get("password");// 根据用户名和密码 获取tokenreturn loginService.getToken(username,password);}
}

实现InfoServiceImpl

package com.kob.backedn2.service.impl.user.account;
import com.kob.backedn2.pojo.User;
import com.kob.backedn2.service.impl.utils.UserDetailsImpl;
import com.kob.backedn2.service.user.account.InfoService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
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 {@Overridepublic Map getInfo() {UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();UserDetailsImpl loginUser = (UserDetailsImpl) authentication.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;}
}

实现InfoController

package com.kob.backedn2.controller.user.account;import com.kob.backedn2.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 {@Autowiredprivate InfoService infoService;@GetMapping("/user/account/info/")public Map getinfo(){return infoService.getInfo();}
}

实现RegisterServiceImpl

package com.kob.backedn2.service.impl.user.account;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kob.backedn2.mapper.UserMapper;
import com.kob.backedn2.pojo.User;
import com.kob.backedn2.service.user.account.RegisterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;import java.util.HashMap;
import java.util.List;
import java.util.Map;@Service
public class RegisterServiceImpl implements RegisterService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic 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(username.length() > 100){map.put("error_message","用户名长度不能大于100");return map;}if(password.length() == 0 || confirmedPassword.length() == 0){map.put("error_message","密码长度不能为0");return map;}if(password.length() > 100 || confirmedPassword.length() > 100){map.put("error_message","密码长度不能大于100");return map;}if(!password.equals(confirmedPassword)){map.put("error_message","两次输入的密码不一致");return map;}QueryWrapper queryWrapper = new QueryWrapper();queryWrapper.eq("username",username);List users = userMapper.selectList(queryWrapper);if(!users.isEmpty()){map.put("error_message","用户名已经存在");return map;}String encodedPassword = passwordEncoder.encode(password);String photo = "https://cdn.acwing.com/media/user/profile/photo/130933_lg_b73ff6b43b.jpg";User user = new User(null,username,password,photo);userMapper.insert(user);map.put("error_message","success");return map;}
}

实现RegisterController

package com.kob.backedn2.controller.user.account;import com.kob.backedn2.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 {@Autowiredprivate 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);}
}

前端页面的实现

  • UserAccountLoginView
  • user.js
import $ from 'jquery'export default {state: {id: "",username: "",photo: "",token: "",is_login: false,},getters: {},mutations: {updateUser(state, user) {state.id = user.id;state.username = user.username;state.photo = user.photo;state.is_login = user.is_login;},updateToken(state, token) {state.token = token;},logout(state) {state.id = "";state.username = "";state.photo = "";state.token = "";state.is_login = false;}},actions: {login(context, data) {$.ajax({url: "http://127.0.0.1:3000/user/account/token/",type: "post",data: {username: data.username,password: data.password,},success(resp) {if (resp.error_message === "success") {context.commit("updateToken", resp.token);data.success(resp);} else {data.error(resp);}},error(resp) {data.error(resp);}});},getinfo(context, data) {$.ajax({url: "http://127.0.0.1:3000/user/account/info/",type: "get",headers: {Authorization: "Bearer " + context.state.token,},success(resp) {if (resp.error_message === "success") {context.commit("updateUser", {...resp,is_login: true,});data.success(resp);} else {data.error(resp);}},error(resp) {data.error(resp);}})},logout(context) {context.commit("logout");}},modules: {}
}

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...