目录
ps:本篇文章篇幅较长,且难度有所提升,希望大家耐心看完,种一棵树最好的时间是十年前,其次是现在

在 pom.xml 中添加下列依赖:
jjwt-api
jjwt-impl
jjwt-jackson
- <dependency>
- <groupId>io.jsonwebtokengroupId>
- <artifactId>jjwt-apiartifactId>
- <version>0.11.2version>
- dependency>
- <dependency>
- <groupId>io.jsonwebtokengroupId>
- <artifactId>jjwt-implartifactId>
- <version>0.11.2version>
- <scope>runtimescope>
- dependency>
- <dependency>
- <groupId>io.jsonwebtokengroupId>
- <artifactId>jjwt-jacksonartifactId>
- <version>0.11.2version>
- <scope>runtimescope>
- dependency>
-

实现 JwtUtil 类
在 backend 目录下创建软件包 utils 并创建 JwtUtil 类。
JwtUtil 类为jwt 工具类,用来创建、解析 jwt token
- package com.kob.backend.utils;
-
- 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 类
在 backend 的 config 目录下创建 cinfig 软件包,并创建 JwtAuthenticationTokenFilter 类。
实现 JwtAuthenticationTokenFilter 类,用来验证 jwt token ,如果验证成功,则将 User 信息注入上下文中。
- package com.kob.backend.config.filter;
-
-
- 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.istack.internal.NotNull;
- import io.jsonwebtoken.Claims;
- 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");
-
- 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类
放行登录、注册等接口。
- 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;
-
- @Configuration
- @EnableWebSecurity
- 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();
- }
-
- @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);
- }
- }

将数据库中的 id 域变为自增。
在 pojo.User 类中添加注解:@TableId(type = IdType.AUTO)
右击 user ,点击 修改表 ,双击 id ,选择 自动增加。同时添加一列 photo,类型设置为 varchar(1000) ,用来存储照片,默认值可以设置为自己的头像。

修改 User ,添加 photo
- package com.kob.backend.pojo;
- //与数据库中的表对应
- import com.baomidou.mybatisplus.annotation.IdType;
- import com.baomidou.mybatisplus.annotation.TableId;
- 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;
- }

实现接口API
实现API需要三个相关类或接口:在 service 下创建一个接口。
在 service 下创建一个类实现这个接口。
在 controller 下创建一个类进行操作。
实现 LoginService
验证用户名密码,验证成功后返回 jwt token(令牌)创建接口:在 service下 创建 user 创建 account 新建一个接口 LoginService
- package com.kob.backend.service.user.account;
-
- import java.util.Map;
-
- public interface LoginService {
- public Map
getToken(String username, String password); -
- }

创建实现类:在 service下 impl 下创建 user 创建 account 新建一个实现类LoginServiceImpl
- 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.boot.autoconfigure.neo4j.Neo4jProperties;
- 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
- public class LoginServiceImpl implements LoginService {
-
- @Autowired
- private AuthenticationManager authenticationManager;
-
- @Override
- public Map
getToken(String username, String password) { - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
-
- Authentication authenticate = authenticationManager.authenticate(authenticationToken);
- UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal();
- User user = loginUser.getUser();
- String jwt = JwtUtil.createJWT(user.getId().toString());
-
- Map
map = new HashMap<>(); - map.put("error_message", "success");
- map.put("token", jwt);
-
- return map;
- }
- }

创建controller:在 controller 创建 user 创建 account 新建一个LoginController
- 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
- public class LoginController {
-
- @Autowired
- private LoginService loginService;
-
- @PostMapping("/user/account/token/")
- public Map
getToken(@RequestParam Map map) { - String username = map.get("username");
- String password = map.get("password");
-
- System.out.println(username + ' ' + password);
- return loginService.getToken(username, password);
- }
- }

配置InforService类
根据令牌返回用户信息。创建接口:在 service下 创建 user 创建 account 新建一个接口 InfoService
- package com.kob.backend.service.user.account;
-
- import java.util.Map;
-
- public interface InfoService {
- public Map
getInfo(); - }

创建实现类:在 service下 impl 下创建 user 创建 account 新建一个实现类InfoServiceImpl
- 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.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 {
-
- /**
- * 根据token返回用户信息
- * @return map存储的信息
- */
- @Override
- public 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;
- }
- }

创建controller:在 controller 创建 user 创建 account 新建一个InfoController
- 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();
- }
- }

配置RegisterService类
注册账号创建接口:在 service下 创建 user 创建 account 新建一个接口 RegisterService
- package com.kob.backend.service.user.account;
-
- import java.util.Map;
-
- public interface RegisterService {
- public Map
register(String username, String password, String confirmedPassword); - }

创建实现类:在 service下 impl 下创建 user 创建 account 新建一个实现类RegisterServiceImpl
- package com.kob.backend.service.impl.user.account;
-
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.kob.backend.mapper.UserMapper;
- import com.kob.backend.pojo.User;
- import com.kob.backend.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 {
-
- @Autowired
- private UserMapper userMapper;
-
- @Autowired
- private PasswordEncoder passwordEncoder;
-
- @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 || confirmedPassword.length() == 0) {
- map.put("error_message", "密码不能为空");
- return map;
- }
-
- if (username.length() > 100) {
- map.put("error_message", "用户名长度不能大于100");
- 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 = "******************************";
- User user = new User(null, username, encodedPassword, photo);
- userMapper.insert(user);
-
- map.put("error_message", "success");
- return map;
- }
- }

创建controller:在 controller 创建 user 创建 account 新建一个RegisterController
- 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);
- }
- }

调试接口API
验证用户登陆:
在 APP.vue 中编写:注意:这里的Authorization: “Bearer “有空格,且token为自己的浏览器的token,需要更改token。
- <NavBar>NavBar>
- <router-view>router-view>
-
- <script>
-
- import NavBar from "@/components/NavBar.vue";
- import "bootstrap/dist/css/bootstrap.min.css";
- import "bootstrap/dist/js/bootstrap";
- import $ from 'jquery'
-
- export default {
- components:{
- NavBar
- },
-
- setup() {
- // 测试LoginService
- $.ajax({
- url: "http://127.0.0.1:8080/user/account/token/",
- type: "post",
- data: {
- username: 'syy',
- password: 'psyy',
- },
- success(resp) {
- console.log(resp);
- },
- error(resp) {
- console.log(resp);
- }
- });
- // 测试InfoService
- $.ajax({
- url: "http://127.0.0.1:8080/user/account/info/",
- type: "get",
- headers: {
- Authorization: "Bearer " + "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4MjliMjQzYjg4YmM0NjdjYmRkMDAwMmNiMzYwZDJiMyIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY1OTU3ODUyMiwiZXhwIjoxNjYwNzg4MTIyfQ.s5nd3RgtDKkPBDDm4P87ET8biZk8H79VMII1p_O9OsA",
- },
- success(resp) {
- console.log(resp);
- },
- error(resp) {
- console.log(resp);
- }
- });
- // 测试RegisterService
- $.ajax({
- url: "http://127.0.0.1:8080/user/account/register/",
- type: "post",
- data: {
- username: "hmy",
- password: "phmy",
- confirmedPassword: "phmy",
- },
- success(resp) {
- console.log(resp);
- },
- error(resp) {
- console.log(resp);
- }
- })
- }
- }
- script>
-
-
- <style>
- body {
- background-image: url("./assets/images/background.png");
- background-size: cover;
- }
- style>


实现两个页面–登陆、注册的前端样式:
从 bootstrap 上去寻找合适的样式:举个例子:
样式:
- <div class="container">
- <div class="row row-cols-2">
- <div class="col">Columndiv>
- <div class="col">Columndiv>
- div>
- div>

- <div class="mb-3">
- <label for="exampleFormControlInput1" class="form-label">Email addresslabel>
- <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
- div>
- <div class="mb-3">
- <label for="exampleFormControlTextarea1" class="form-label">Example textarealabel>
- <textarea class="form-control" id="exampleFormControlTextarea1" rows="3">textarea>
- div>
-
提交按钮
<button type="button" class="btn btn-primary">Primarybutton>
创建页面:
在 views 目录下创建 user ,新建两个文件 UserAccountLoginView.vue 和 UserAccountRegisterView.vue 。
实现 UserAccountRegisterView.vue 页面:
- <template>
- <ContentField>
- 注册
- ContentField>
- template>
-
- <script>
- import ContentField from '../../../components/ContentField.vue'
-
- export default {
- components: {
- ContentField
- }
- }
- script>
-
- <style scoped>
- style>

实现 UserAccountLoginView.vue 页面:
- <template>
- <ContentField>
- <div class="row justify-content-md-center">
- <div class="col-3">
- <form>
- <div class="mb-3">
- <label for="username" class="form-label">用户名label>
- <input v-model="username" type="text" class="form-control" id="username" placeholder="请输入用户名">
- div>
- <div class="mb-3">
- <label for="password" class="form-label">密码label>
- <input v-model="password" type="password" class="form-control" id="password" placeholder="请输入密码">
- div>
- <div class="error-message">{{ error_message }}div>
- <button type="submit" class="btn btn-primary">提交button>
- form>
- div>
- div>
- ContentField>
- template>
-
- <script>
- import ContentField from '../../../components/ContentField.vue'
-
- export default {
- components: {
- ContentField
- }
- }
- script>
-
- <style scoped>
- button {
- width: 100%;
- }
- div.error-message {
- color: red;
- }
- style>

在router目录下的index.js中加入路径
修改 index.js:
- import UserAccountLoginView from '../views/user/account/UserAccountLoginView'
- import UserAccountRegisterView from '../views/user/account/UserAccountRegisterView'
-
- const routes = [
- {
- path: "/user/account/login",
- name: "user_account_login",
- component: UserAccountLoginView,
- },
- {
- path: "/user/account/register",
- name: "user_account_register",
- component: UserAccountRegisterView,
- }
-
- ]
-
- const router = createRouter({
- history: createWebHistory(),
- routes
- })
-
- export default router

在store下的user.js存储用户信息
在 store 下创建 user.js
- import $ from 'jquery'
-
- export default {
- state: {
- id: "",
- username: "",
- password: "",
- 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;
- },
- },
- actions: {
-
- },
- modules: {
- }
- }

把user加入到全局module
在 store 下的 index.js
- import { createStore } from 'vuex'
- import ModuleUser from './user'
-
- export default createStore({
- state: {
- },
- getters: {
- },
- mutations: {
- },
- actions: {
- },
- modules: {
- user: ModuleUser,
- }
- })

添加辅助函数login
在 store 下的 user.js 修改。
- import $ from 'jquery'
-
- export default {
- state: {
- id: "",
- username: "",
- password: "",
- 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;
- },
- },
- actions: {
- login(context, data) {
- $.ajax({
- url: "http://127.0.0.1:8080/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);
- }
- });
- },
- },
- modules: {
- }
- }

在 UserAccountLoginView.vue 中实现
- import ContentField from '../../../components/ContentField.vue'
- import { useStore } from 'vuex'
- import { ref } from 'vue'
-
- export default {
- components: {
- ContentField
- },
- setup() {
- const store = useStore();
- let username = ref('');
- let password = ref('');
- let error_message = ref('');
- //触发函数
- const login = () => {
- error_message.value = "";
- store.dispatch("login", {
- username: username.value,
- password: password.value,
- success(resp) {
- console.log(resp);
- },
- error(resp) {
- console.log(resp);
- }
-
- /*
- success() {
- //登陆成功后获取用户信息
- store.dispatch("getinfo", {
- success() {
- router.push({ name: 'home' });
- console.log(store.state.user);
- }
- })
- },
- error() {
- error_message.value = "用户名或密码错误";
- }
- */
- })
- }
-
- return {
- username,
- password,
- error_message,
- login,
- }
- }
- }

把内容和变量绑定起来:
- <form @submit.prevent="login">
- <div class="mb-3">
- <label for="username" class="form-label">用户名label>
- <input v-model="username" type="text" class="form-control" id="username" placeholder="请输入用户名">
- div>
- <div class="mb-3">
- <label for="password" class="form-label">密码label>
- <input v-model="password" type="password" class="form-control" id="password" placeholder="请输入密码">
- div>
- <div class="error-message">{{ error_message }}div>
- <button type="submit" class="btn btn-primary">提交button>
- form>

在登陆界面测试
输入用户名和密码,获取 token。

用户名和密码输入正确,点击提交跳到主页面
在 UserAccountLoginView.vue 中实现
- import ContentField from '../../../components/ContentField.vue'
- import { useStore } from 'vuex'
- import { ref } from 'vue'
- import router from '../../../router/index'
-
- export default {
- components: {
- ContentField
- },
- setup() {
- const store = useStore();
- let username = ref('');
- let password = ref('');
- let error_message = ref('');
- //触发函数
- const login = () => {
- error_message.value = "";
- store.dispatch("login", {
- username: username.value,
- password: password.value,
- success() {
- //成功后跳转到主页面
- router.push({name: 'home'});
- },
- error() {
- error_message.value = "用户名或密码错误";
- }
-
- /*
- success() {
- //登陆成功后获取用户信息
- store.dispatch("getinfo", {
- success() {
- router.push({ name: 'home' });
- console.log(store.state.user);
- }
- })
- },
- error() {
- error_message.value = "用户名或密码错误";
- }
- */
- })
- }
-
- return {
- username,
- password,
- error_message,
- login,
- }
- }
- }

登陆成功后获取用户的信息
在 user.js 中添加辅助函数
- import $ from 'jquery'
-
- export default {
- state: {
- id: "",
- username: "",
- password: "",
- 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;
- },
- },
- actions: {
- login(context, data) {
- $.ajax({
- url: "http://127.0.0.1:8080/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:8080/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: {
- }
- }

修改 UserAccountLoginView.vue
- import ContentField from '../../../components/ContentField.vue'
- import { useStore } from 'vuex'
- import { ref } from 'vue'
- import router from '../../../router/index'
-
- export default {
- components: {
- ContentField
- },
- setup() {
- const store = useStore();
- let username = ref('');
- let password = ref('');
- let error_message = ref('');
- //触发函数
- const login = () => {
- error_message.value = "";
- store.dispatch("login", {
- username: username.value,
- password: password.value,
- success() {
- //登陆成功后获取用户信息
- store.dispatch("getinfo", {
- success(resp) {
- router.push({ name: 'home' });
- console.log(store.state.user);
- }
- })
- },
- error() {
- error_message.value = "用户名或密码错误";
- }
-
- })
- }
-
- return {
- username,
- password,
- error_message,
- login,
- }
- }
- }


把结果返回到右上角个人信息 – 修改导航栏
修改 NavBar.vue:
- <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
- <div class="container">
- <router-link class="navbar-brand" :to="{name: 'home'}">King Of Botsrouter-link>
- <div class="collapse navbar-collapse" id="navbarText">
- <ul class="navbar-nav me-auto mb-2 mb-lg-0">
- <li class="nav-item">
- <router-link :class="route_name == 'pk_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'pk_index'}">对战router-link>
- li>
- <li class="nav-item">
- <router-link :class="route_name == 'record_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'record_index'}">对局列表router-link>
- li>
- <li class="nav-item">
- <router-link :class="route_name == 'ranklist_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'ranklist_index'}">排行榜router-link>
- li>
- ul>
- <ul class="navbar-nav" v-if="$store.state.user.is_login">
- <li class="nav-item dropdown">
- <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
- {{ $store.state.user.username }}
- a>
- <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
- <li>
-
- <router-link class="dropdown-item" :to="{name: 'user_bot_index'}">我的Botrouter-link>
- li>
- <li><hr class="dropdown-divider">li>
- <li><a class="dropdown-item" href="#" @click="logout">退出a>li>
- ul>
- li>
- ul>
- <ul class="navbar-nav" v-else>
- <li class="nav-item">
- <router-link class="nav-link" :to="{name: 'user_account_login' }" role="button">
- 登录
- router-link>
- li>
- <li class="nav-item">
- <router-link class="nav-link" :to="{name: 'user_account_register'}" role="button">
- 注册
- router-link>
- li>
- ul>
- div>
- div>
- nav>
- template>
-
- <script>
- import { useRoute } from 'vue-router'
- import { computed } from 'vue'
- import { useStore } from 'vuex';
-
- export default {
- setup() {
- const store = useStore();
- const route = useRoute();
- let route_name = computed(() => route.name)
-
- const logout = () => {
- store.dispatch("logout");
- }
-
- return {
- route_name,
- logout
- }
- }
- }
- script>
-
- <style scoped>
-
- style>

退出登陆
user.js 添加辅助函数:
- mutations: {
- logout(state) {
- state.id = "";
- state.username = "";
- state.photo = "";
- state.token = "";
- state.is_login = false;
- }
- },
- actions: {
- logout(context) {
- context.commit("logout");
- }
- },

在 navabar.vue 添加组件:
- <a class="dropdown-item" href="#" @click="logout">退出a>
-
- <script>
- import { useRoute } from 'vue-router'
- import { computed } from 'vue'
- import { useStore } from 'vuex';
-
- export default {
- setup() {
- const store = useStore();
- const route = useRoute();
- let route_name = computed(() => route.name)
-
- const logout = () => {
- store.dispatch("logout");
- }
-
- return {
- route_name,
- logout
- }
- }
- }
- script>

大功告成,记得git 维护~
