• 项目实战——实现注册和登录模块


    目录

    一、整体框架

    二、实现JwtToken验证

     1、添加依赖

    2、编写、修改相关类

     三、实现后端 API

     四、实现前端的登录,注册界面



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

    一、整体框架

    4.2 实现注册与登录模块

    二、实现JwtToken验证

     1、添加依赖

    在 pom.xml 中添加下列依赖:

    jjwt-api
    jjwt-impl
    jjwt-jackson

    1. <dependency>
    2. <groupId>io.jsonwebtokengroupId>
    3. <artifactId>jjwt-apiartifactId>
    4. <version>0.11.2version>
    5. dependency>
    6. <dependency>
    7. <groupId>io.jsonwebtokengroupId>
    8. <artifactId>jjwt-implartifactId>
    9. <version>0.11.2version>
    10. <scope>runtimescope>
    11. dependency>
    12. <dependency>
    13. <groupId>io.jsonwebtokengroupId>
    14. <artifactId>jjwt-jacksonartifactId>
    15. <version>0.11.2version>
    16. <scope>runtimescope>
    17. dependency>

    jwt添加依赖

    2、编写、修改相关类

    实现 JwtUtil 类
    在 backend 目录下创建软件包 utils 并创建 JwtUtil 类。
    JwtUtil 类为jwt 工具类,用来创建、解析 jwt token

    1. package com.kob.backend.utils;
    2. import io.jsonwebtoken.Claims;
    3. import io.jsonwebtoken.JwtBuilder;
    4. import io.jsonwebtoken.Jwts;
    5. import io.jsonwebtoken.SignatureAlgorithm;
    6. import org.springframework.stereotype.Component;
    7. import javax.crypto.SecretKey;
    8. import javax.crypto.spec.SecretKeySpec;
    9. import java.util.Base64;
    10. import java.util.Date;
    11. import java.util.UUID;
    12. @Component
    13. public class JwtUtil {
    14. public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14; // 有效期14天
    15. public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac";
    16. public static String getUUID() {
    17. return UUID.randomUUID().toString().replaceAll("-", "");
    18. }
    19. public static String createJWT(String subject) {
    20. JwtBuilder builder = getJwtBuilder(subject, null, getUUID());
    21. return builder.compact();
    22. }
    23. private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
    24. SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
    25. SecretKey secretKey = generalKey();
    26. long nowMillis = System.currentTimeMillis();
    27. Date now = new Date(nowMillis);
    28. if (ttlMillis == null) {
    29. ttlMillis = JwtUtil.JWT_TTL;
    30. }
    31. long expMillis = nowMillis + ttlMillis;
    32. Date expDate = new Date(expMillis);
    33. return Jwts.builder()
    34. .setId(uuid)
    35. .setSubject(subject)
    36. .setIssuer("sg")
    37. .setIssuedAt(now)
    38. .signWith(signatureAlgorithm, secretKey)
    39. .setExpiration(expDate);
    40. }
    41. public static SecretKey generalKey() {
    42. byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
    43. return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");
    44. }
    45. public static Claims parseJWT(String jwt) throws Exception {
    46. SecretKey secretKey = generalKey();
    47. return Jwts.parserBuilder()
    48. .setSigningKey(secretKey)
    49. .build()
    50. .parseClaimsJws(jwt)
    51. .getBody();
    52. }
    53. }

     jwt-utils

     实现 JwtAuthenticationTokenFilter 类
    在 backend 的 config 目录下创建 cinfig 软件包,并创建 JwtAuthenticationTokenFilter 类。
    实现 JwtAuthenticationTokenFilter 类,用来验证 jwt token ,如果验证成功,则将 User 信息注入上下文中。

    1. package com.kob.backend.config.filter;
    2. import com.kob.backend.mapper.UserMapper;
    3. import com.kob.backend.pojo.User;
    4. import com.kob.backend.service.impl.utils.UserDetailsImpl;
    5. import com.kob.backend.utils.JwtUtil;
    6. import com.sun.istack.internal.NotNull;
    7. import io.jsonwebtoken.Claims;
    8. import org.springframework.beans.factory.annotation.Autowired;
    9. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    10. import org.springframework.security.core.context.SecurityContextHolder;
    11. import org.springframework.stereotype.Component;
    12. import org.springframework.util.StringUtils;
    13. import org.springframework.web.filter.OncePerRequestFilter;
    14. import javax.servlet.FilterChain;
    15. import javax.servlet.ServletException;
    16. import javax.servlet.http.HttpServletRequest;
    17. import javax.servlet.http.HttpServletResponse;
    18. import java.io.IOException;
    19. @Component
    20. public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    21. @Autowired
    22. private UserMapper userMapper;
    23. @Override
    24. protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
    25. String token = request.getHeader("Authorization");
    26. if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) {
    27. filterChain.doFilter(request, response);
    28. return;
    29. }
    30. token = token.substring(7);
    31. String userid;
    32. try {
    33. Claims claims = JwtUtil.parseJWT(token);
    34. userid = claims.getSubject();
    35. } catch (Exception e) {
    36. throw new RuntimeException(e);
    37. }
    38. User user = userMapper.selectById(Integer.parseInt(userid));
    39. if (user == null) {
    40. throw new RuntimeException("用户名未登录");
    41. }
    42. UserDetailsImpl loginUser = new UserDetailsImpl(user);
    43. UsernamePasswordAuthenticationToken authenticationToken =
    44. new UsernamePasswordAuthenticationToken(loginUser, null, null);
    45. SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    46. filterChain.doFilter(request, response);
    47. }
    48. }

    在这里插入图片描述

     配置config.SecurityConfig类
    放行登录、注册等接口。

    1. package com.kob.backend.config;
    2. import com.kob.backend.config.filter.JwtAuthenticationTokenFilter;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.context.annotation.Bean;
    5. import org.springframework.context.annotation.Configuration;
    6. import org.springframework.http.HttpMethod;
    7. import org.springframework.security.authentication.AuthenticationManager;
    8. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    9. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    10. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    11. import org.springframework.security.config.http.SessionCreationPolicy;
    12. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    13. import org.springframework.security.crypto.password.PasswordEncoder;
    14. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    15. @Configuration
    16. @EnableWebSecurity
    17. public class SecurityConfig extends WebSecurityConfigurerAdapter {
    18. @Autowired
    19. private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    20. @Bean
    21. public PasswordEncoder passwordEncoder() {
    22. return new BCryptPasswordEncoder();
    23. }
    24. @Bean
    25. @Override
    26. public AuthenticationManager authenticationManagerBean() throws Exception {
    27. return super.authenticationManagerBean();
    28. }
    29. @Override
    30. protected void configure(HttpSecurity http) throws Exception {
    31. http.csrf().disable()
    32. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    33. .and()
    34. .authorizeRequests()
    35. .antMatchers("/user/account/token/", "/user/account/register/").permitAll()
    36. .antMatchers(HttpMethod.OPTIONS).permitAll()
    37. .anyRequest().authenticated();
    38. http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    39. }
    40. }

    security-config

     三、实现后端 API

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

    修改数据库

     修改 User ,添加 photo

    1. package com.kob.backend.pojo;
    2. //与数据库中的表对应
    3. import com.baomidou.mybatisplus.annotation.IdType;
    4. import com.baomidou.mybatisplus.annotation.TableId;
    5. import lombok.AllArgsConstructor;
    6. import lombok.Data;
    7. import lombok.NoArgsConstructor;
    8. @Data
    9. @NoArgsConstructor
    10. @AllArgsConstructor
    11. public class User {
    12. @TableId(type = IdType.AUTO)
    13. private Integer id;
    14. private String username;
    15. private String password;
    16. private String photo;
    17. }

    修改user

     实现接口API
    实现API需要三个相关类或接口:

    在 service 下创建一个接口。
    在 service 下创建一个类实现这个接口。
    在 controller 下创建一个类进行操作。

    实现 LoginService
    验证用户名密码,验证成功后返回 jwt token(令牌)

    创建接口:在 service下 创建 user 创建 account 新建一个接口 LoginService

    1. package com.kob.backend.service.user.account;
    2. import java.util.Map;
    3. public interface LoginService {
    4. public Map getToken(String username, String password);
    5. }

    login接口

     创建实现类:在 service下 impl 下创建 user 创建 account 新建一个实现类LoginServiceImpl

    1. package com.kob.backend.service.impl.user.account;
    2. import com.kob.backend.pojo.User;
    3. import com.kob.backend.service.impl.utils.UserDetailsImpl;
    4. import com.kob.backend.service.user.account.LoginService;
    5. import com.kob.backend.utils.JwtUtil;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties;
    8. import org.springframework.security.authentication.AuthenticationManager;
    9. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    10. import org.springframework.security.core.Authentication;
    11. import org.springframework.stereotype.Service;
    12. import java.util.HashMap;
    13. import java.util.Map;
    14. @Service
    15. public class LoginServiceImpl implements LoginService {
    16. @Autowired
    17. private AuthenticationManager authenticationManager;
    18. @Override
    19. public Map getToken(String username, String password) {
    20. UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
    21. Authentication authenticate = authenticationManager.authenticate(authenticationToken);
    22. UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal();
    23. User user = loginUser.getUser();
    24. String jwt = JwtUtil.createJWT(user.getId().toString());
    25. Map map = new HashMap<>();
    26. map.put("error_message", "success");
    27. map.put("token", jwt);
    28. return map;
    29. }
    30. }

    login实现类

     创建controller:在 controller 创建 user 创建 account 新建一个LoginController

    1. package com.kob.backend.controller.user.account;
    2. import com.kob.backend.service.user.account.LoginService;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.web.bind.annotation.PostMapping;
    5. import org.springframework.web.bind.annotation.RequestParam;
    6. import org.springframework.web.bind.annotation.RestController;
    7. import java.util.Map;
    8. @RestController
    9. public class LoginController {
    10. @Autowired
    11. private LoginService loginService;
    12. @PostMapping("/user/account/token/")
    13. public Map getToken(@RequestParam Map map) {
    14. String username = map.get("username");
    15. String password = map.get("password");
    16. System.out.println(username + ' ' + password);
    17. return loginService.getToken(username, password);
    18. }
    19. }

    在这里插入图片描述

     配置InforService类
    根据令牌返回用户信息。

    创建接口:在 service下 创建 user 创建 account 新建一个接口 InfoService

    1. package com.kob.backend.service.user.account;
    2. import java.util.Map;
    3. public interface InfoService {
    4. public Map getInfo();
    5. }

    在这里插入图片描述

     创建实现类:在 service下 impl 下创建 user 创建 account 新建一个实现类InfoServiceImpl

    1. package com.kob.backend.service.impl.user.account;
    2. import com.kob.backend.pojo.User;
    3. import com.kob.backend.service.impl.utils.UserDetailsImpl;
    4. import com.kob.backend.service.user.account.InfoService;
    5. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    6. import org.springframework.security.core.context.SecurityContextHolder;
    7. import org.springframework.stereotype.Service;
    8. import java.util.HashMap;
    9. import java.util.Map;
    10. @Service
    11. public class InfoServiceImpl implements InfoService {
    12. /**
    13. * 根据token返回用户信息
    14. * @return map存储的信息
    15. */
    16. @Override
    17. public Map getInfo() {
    18. UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
    19. UserDetailsImpl loginUser = (UserDetailsImpl) authentication.getPrincipal();
    20. User user = loginUser.getUser();
    21. Map map = new HashMap<>();
    22. map.put("error_message", "success");
    23. map.put("id", user.getId().toString());
    24. map.put("username", user.getUsername());
    25. map.put("photo", user.getPhoto());
    26. return map;
    27. }
    28. }

    在这里插入图片描述

     创建controller:在 controller 创建 user 创建 account 新建一个InfoController

    1. package com.kob.backend.controller.user.account;
    2. import com.kob.backend.service.user.account.InfoService;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.web.bind.annotation.GetMapping;
    5. import org.springframework.web.bind.annotation.RestController;
    6. import java.util.Map;
    7. @RestController
    8. public class InfoController {
    9. @Autowired
    10. private InfoService infoService;
    11. @GetMapping("/user/account/info/")
    12. public Map getInfo() {
    13. return infoService.getInfo();
    14. }
    15. }

    在这里插入图片描述

     配置RegisterService类
    注册账号

    创建接口:在 service下 创建 user 创建 account 新建一个接口 RegisterService

    1. package com.kob.backend.service.user.account;
    2. import java.util.Map;
    3. public interface RegisterService {
    4. public Map register(String username, String password, String confirmedPassword);
    5. }

    在这里插入图片描述

     创建实现类:在 service下 impl 下创建 user 创建 account 新建一个实现类RegisterServiceImpl

    1. package com.kob.backend.service.impl.user.account;
    2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    3. import com.kob.backend.mapper.UserMapper;
    4. import com.kob.backend.pojo.User;
    5. import com.kob.backend.service.user.account.RegisterService;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.security.crypto.password.PasswordEncoder;
    8. import org.springframework.stereotype.Service;
    9. import java.util.HashMap;
    10. import java.util.List;
    11. import java.util.Map;
    12. @Service
    13. public class RegisterServiceImpl implements RegisterService {
    14. @Autowired
    15. private UserMapper userMapper;
    16. @Autowired
    17. private PasswordEncoder passwordEncoder;
    18. @Override
    19. public Map register(String username, String password, String confirmedPassword) {
    20. Map map = new HashMap<>();
    21. if (username == null) {
    22. map.put("error_message", "用户名不能为空");
    23. return map;
    24. }
    25. if (password == null || confirmedPassword == null) {
    26. map.put("error_message", "密码不能为空");
    27. return map;
    28. }
    29. //删除首尾的空白字符
    30. username = username.trim();
    31. if (username.length() == 0) {
    32. map.put("error_message", "用户名不能为空");
    33. return map;
    34. }
    35. if (password.length() == 0 || confirmedPassword.length() == 0) {
    36. map.put("error_message", "密码不能为空");
    37. return map;
    38. }
    39. if (username.length() > 100) {
    40. map.put("error_message", "用户名长度不能大于100");
    41. return map;
    42. }
    43. if (password.length() > 100 || confirmedPassword.length() > 100) {
    44. map.put("error_message", "密码不能大于100");
    45. return map;
    46. }
    47. if (!password.equals(confirmedPassword)) {
    48. map.put("error_message", "两次输入的密码不一致");
    49. return map;
    50. }
    51. //查询用户名是否重复
    52. QueryWrapper queryWrapper = new QueryWrapper();
    53. queryWrapper.eq("username", username);
    54. List users = userMapper.selectList(queryWrapper);
    55. if (!users.isEmpty()) {
    56. map.put("error_message", "用户名已存在");
    57. return map;
    58. }
    59. // 添加一个新用户
    60. String encodedPassword = passwordEncoder.encode(password);
    61. //输入自己的图片地址
    62. String photo = "******************************";
    63. User user = new User(null, username, encodedPassword, photo);
    64. userMapper.insert(user);
    65. map.put("error_message", "success");
    66. return map;
    67. }
    68. }

    在这里插入图片描述

     创建controller:在 controller 创建 user 创建 account 新建一个RegisterController

    1. package com.kob.backend.controller.user.account;
    2. import com.kob.backend.service.user.account.RegisterService;
    3. import org.springframework.beans.factory.annotation.Autowired;
    4. import org.springframework.web.bind.annotation.PostMapping;
    5. import org.springframework.web.bind.annotation.RequestParam;
    6. import org.springframework.web.bind.annotation.RestController;
    7. import java.util.Map;
    8. @RestController
    9. public class RegisterController {
    10. @Autowired
    11. private RegisterService registerService;
    12. @PostMapping("/user/account/register/")
    13. public Map register(@RequestParam Map map) {
    14. String username = map.get("username");
    15. String password = map.get("password");
    16. String confirmedPassword = map.get("confirmedPassword");
    17. return registerService.register(username, password, confirmedPassword);
    18. }
    19. }

    在这里插入图片描述

     调试接口API
    验证用户登陆:
    在 APP.vue 中编写:

    注意:这里的Authorization: “Bearer “有空格,且token为自己的浏览器的token,需要更改token。

    1. <script>
    2. import NavBar from "@/components/NavBar.vue";
    3. import "bootstrap/dist/css/bootstrap.min.css";
    4. import "bootstrap/dist/js/bootstrap";
    5. import $ from 'jquery'
    6. export default {
    7. components:{
    8. NavBar
    9. },
    10. setup() {
    11. // 测试LoginService
    12. $.ajax({
    13. url: "http://127.0.0.1:8080/user/account/token/",
    14. type: "post",
    15. data: {
    16. username: 'syy',
    17. password: 'psyy',
    18. },
    19. success(resp) {
    20. console.log(resp);
    21. },
    22. error(resp) {
    23. console.log(resp);
    24. }
    25. });
    26. // 测试InfoService
    27. $.ajax({
    28. url: "http://127.0.0.1:8080/user/account/info/",
    29. type: "get",
    30. headers: {
    31. Authorization: "Bearer " + "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4MjliMjQzYjg4YmM0NjdjYmRkMDAwMmNiMzYwZDJiMyIsInN1YiI6IjEiLCJpc3MiOiJzZyIsImlhdCI6MTY1OTU3ODUyMiwiZXhwIjoxNjYwNzg4MTIyfQ.s5nd3RgtDKkPBDDm4P87ET8biZk8H79VMII1p_O9OsA",
    32. },
    33. success(resp) {
    34. console.log(resp);
    35. },
    36. error(resp) {
    37. console.log(resp);
    38. }
    39. });
    40. // 测试RegisterService
    41. $.ajax({
    42. url: "http://127.0.0.1:8080/user/account/register/",
    43. type: "post",
    44. data: {
    45. username: "hmy",
    46. password: "phmy",
    47. confirmedPassword: "phmy",
    48. },
    49. success(resp) {
    50. console.log(resp);
    51. },
    52. error(resp) {
    53. console.log(resp);
    54. }
    55. })
    56. }
    57. }
    58. script>
    59. <style>
    60. body {
    61. background-image: url("./assets/images/background.png");
    62. background-size: cover;
    63. }
    64. style>

    在这里插入图片描述

     测试成功

     四、实现前端的登录,注册界面

    实现两个页面–登陆、注册的前端样式:
    从 bootstrap 上去寻找合适的样式:

    举个例子:

    样式:

    1. <div class="container">
    2. <div class="row row-cols-2">
    3. <div class="col">Columndiv>
    4. <div class="col">Columndiv>
    5. div>
    6. div>

    在这里插入图片描述

    1. <div class="mb-3">
    2. <label for="exampleFormControlInput1" class="form-label">Email addresslabel>
    3. <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com">
    4. div>
    5. <div class="mb-3">
    6. <label for="exampleFormControlTextarea1" class="form-label">Example textarealabel>
    7. <textarea class="form-control" id="exampleFormControlTextarea1" rows="3">textarea>
    8. div>

     提交按钮 

    <button type="button" class="btn btn-primary">Primarybutton>

    创建页面:
    在 views 目录下创建 user ,新建两个文件 UserAccountLoginView.vue 和 UserAccountRegisterView.vue 。

    实现 UserAccountRegisterView.vue 页面:

    1. <template>
    2. <ContentField>
    3. 注册
    4. ContentField>
    5. template>
    6. <script>
    7. import ContentField from '../../../components/ContentField.vue'
    8. export default {
    9. components: {
    10. ContentField
    11. }
    12. }
    13. script>
    14. <style scoped>
    15. style>

    在这里插入图片描述

     实现 UserAccountLoginView.vue 页面:

    1. <template>
    2. <ContentField>
    3. <div class="row justify-content-md-center">
    4. <div class="col-3">
    5. <form>
    6. <div class="mb-3">
    7. <label for="username" class="form-label">用户名label>
    8. <input v-model="username" type="text" class="form-control" id="username" placeholder="请输入用户名">
    9. div>
    10. <div class="mb-3">
    11. <label for="password" class="form-label">密码label>
    12. <input v-model="password" type="password" class="form-control" id="password" placeholder="请输入密码">
    13. div>
    14. <div class="error-message">{{ error_message }}div>
    15. <button type="submit" class="btn btn-primary">提交button>
    16. form>
    17. div>
    18. div>
    19. ContentField>
    20. template>
    21. <script>
    22. import ContentField from '../../../components/ContentField.vue'
    23. export default {
    24. components: {
    25. ContentField
    26. }
    27. }
    28. script>
    29. <style scoped>
    30. button {
    31. width: 100%;
    32. }
    33. div.error-message {
    34. color: red;
    35. }
    36. style>

    在这里插入图片描述

     在router目录下的index.js中加入路径

    修改 index.js:

    1. import UserAccountLoginView from '../views/user/account/UserAccountLoginView'
    2. import UserAccountRegisterView from '../views/user/account/UserAccountRegisterView'
    3. const routes = [
    4. {
    5. path: "/user/account/login",
    6. name: "user_account_login",
    7. component: UserAccountLoginView,
    8. },
    9. {
    10. path: "/user/account/register",
    11. name: "user_account_register",
    12. component: UserAccountRegisterView,
    13. }
    14. ]
    15. const router = createRouter({
    16. history: createWebHistory(),
    17. routes
    18. })
    19. export default router

    在这里插入图片描述

    在store下的user.js存储用户信息

    在 store 下创建 user.js

    1. import $ from 'jquery'
    2. export default {
    3. state: {
    4. id: "",
    5. username: "",
    6. password: "",
    7. photo: "",
    8. token: "",
    9. is_login: false,
    10. },
    11. getters: {
    12. },
    13. mutations: {
    14. updateUser(state, user) {
    15. state.id = user.id;
    16. state.username = user.username;
    17. state.photo = user.photo;
    18. state.is_login = user.is_login;
    19. },
    20. updateToken(state, token) {
    21. state.token = token;
    22. },
    23. },
    24. actions: {
    25. },
    26. modules: {
    27. }
    28. }

    在这里插入图片描述

     把user加入到全局module
    在 store 下的 index.js

    1. import { createStore } from 'vuex'
    2. import ModuleUser from './user'
    3. export default createStore({
    4. state: {
    5. },
    6. getters: {
    7. },
    8. mutations: {
    9. },
    10. actions: {
    11. },
    12. modules: {
    13. user: ModuleUser,
    14. }
    15. })

    在这里插入图片描述

     添加辅助函数login
    在 store 下的 user.js 修改。

    1. import $ from 'jquery'
    2. export default {
    3. state: {
    4. id: "",
    5. username: "",
    6. password: "",
    7. photo: "",
    8. token: "",
    9. is_login: false,
    10. },
    11. getters: {
    12. },
    13. mutations: {
    14. updateUser(state, user) {
    15. state.id = user.id;
    16. state.username = user.username;
    17. state.photo = user.photo;
    18. state.is_login = user.is_login;
    19. },
    20. updateToken(state, token) {
    21. state.token = token;
    22. },
    23. },
    24. actions: {
    25. login(context, data) {
    26. $.ajax({
    27. url: "http://127.0.0.1:8080/user/account/token/",
    28. type: "post",
    29. data: {
    30. username: data.username,
    31. password: data.password,
    32. },
    33. success(resp) {
    34. if (resp.error_message === "success") {
    35. context.commit("updateToken", resp.token);
    36. data.success(resp);
    37. } else {
    38. data.error(resp);
    39. }
    40. },
    41. error(resp) {
    42. data.error(resp);
    43. }
    44. });
    45. },
    46. },
    47. modules: {
    48. }
    49. }

    在这里插入图片描述

     在 UserAccountLoginView.vue 中实现

    在这里插入图片描述

      把内容和变量绑定起来:

    1. <form @submit.prevent="login">
    2. <div class="mb-3">
    3. <label for="username" class="form-label">用户名label>
    4. <input v-model="username" type="text" class="form-control" id="username" placeholder="请输入用户名">
    5. div>
    6. <div class="mb-3">
    7. <label for="password" class="form-label">密码label>
    8. <input v-model="password" type="password" class="form-control" id="password" placeholder="请输入密码">
    9. div>
    10. <div class="error-message">{{ error_message }}div>
    11. <button type="submit" class="btn btn-primary">提交button>
    12. form>

    在这里插入图片描述

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

    在这里插入图片描述

     用户名和密码输入正确,点击提交跳到主页面
    在 UserAccountLoginView.vue 中实现

    在这里插入图片描述

     登陆成功后获取用户的信息
    在 user.js 中添加辅助函数

    1. import $ from 'jquery'
    2. export default {
    3. state: {
    4. id: "",
    5. username: "",
    6. password: "",
    7. photo: "",
    8. token: "",
    9. is_login: false,
    10. },
    11. getters: {
    12. },
    13. mutations: {
    14. updateUser(state, user) {
    15. state.id = user.id;
    16. state.username = user.username;
    17. state.photo = user.photo;
    18. state.is_login = user.is_login;
    19. },
    20. updateToken(state, token) {
    21. state.token = token;
    22. },
    23. },
    24. actions: {
    25. login(context, data) {
    26. $.ajax({
    27. url: "http://127.0.0.1:8080/user/account/token/",
    28. type: "post",
    29. data: {
    30. username: data.username,
    31. password: data.password,
    32. },
    33. success(resp) {
    34. if (resp.error_message === "success") {
    35. context.commit("updateToken", resp.token);
    36. data.success(resp);
    37. } else {
    38. data.error(resp);
    39. }
    40. },
    41. error(resp) {
    42. data.error(resp);
    43. }
    44. });
    45. },
    46. getinfo(context, data) {
    47. $.ajax({
    48. url: "http://127.0.0.1:8080/user/account/info/",
    49. type: "get",
    50. headers: {
    51. Authorization: "Bearer " + context.state.token,
    52. },
    53. //成功就更新用户。
    54. success(resp) {
    55. if (resp.error_message === "success") {
    56. context.commit("updateUser", {
    57. ...resp,
    58. is_login: true,
    59. });
    60. data.success(resp);
    61. } else {
    62. data.error(resp);
    63. }
    64. },
    65. error(resp) {
    66. data.error(resp);
    67. }
    68. });
    69. },
    70. logout(context) {
    71. context.commit("logout");
    72. }
    73. },
    74. modules: {
    75. }
    76. }

    在这里插入图片描述

     修改 UserAccountLoginView.vue

    在这里插入图片描述

     在这里插入图片描述

     把结果返回到右上角个人信息 – 修改导航栏

    修改 NavBar.vue: