😊 If the writing can help you, can you give me a thumbs up? Your support is my motivation to write. 😊
This article takes about 30 minutes to read, and about 3-5 hours to write and think. Suggestion: The code can be copied manually, but not copied.
1. Overall framework
2. Implement JwtToken verification
2.1 Adding Dependencies
In pom Add the following dependencies to xml:
jjwt-api
jjwt-impl
jjwt-jackson
Click Reload after adding.
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency>
As shown in the figure below:
2.2 Preparation and modification of related categories
1. Implement JwtUtil class
Create the software package utils in the backend directory and create the JwtUtil class.
The JwtUtil class is a jwt tool class used to create and parse jwt token s.
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; // Valid for 14 days 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(); } }
2. Implement JwtAuthenticationTokenFilter class
Create the cinfig package in the config directory of the backend, and create the JwtAuthenticationTokenFilter class.
Implement the JwtAuthenticationTokenFilter class to verify the jwt token. If the verification is successful, the User information will be injected into the context.
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("User name not logged in"); } UserDetailsImpl loginUser = new UserDetailsImpl(user); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, null); SecurityContextHolder.getContext().setAuthentication(authenticationToken); filterChain.doFilter(request, response); } }
3. Configure the config.SecurityConfig class
Release login, registration and other interfaces.
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); } }
3. Implement back-end API
3.1 Modifying the database
- Change the id field in the database to auto increment.
- In pojo Add annotation to the User class: @ TableId (type=IdType. AUTO)
Right click user, click Modify Table, double-click id, and select Auto Add. At the same time, add a column of photos. The type is set to varchar(1000) to store photos. The default value can be set to your own avatar.
Modify User and add photo
package com.kob.backend.pojo; //Corresponds to the table in the database 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; }
3.2 Implementation of interface API
Three related classes or interfaces are required to implement the API:
- Create an interface under service.
- Create a class under service to implement this interface.
- Create a class under the controller to operate.
1. Implement LoginService
Verify the user name and password, and return the jwt token after successful verification
Create an interface: create a user under service, create an account, and create an interface LoginService
package com.kob.backend.service.user.account; import java.util.Map; public interface LoginService { public Map<String, String> getToken(String username, String password); }
Create an implementation class: create a user under impl under service, create an account, create a new implementation class, 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<String, String> 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<String, String> map = new HashMap<>(); map.put("error_message", "success"); map.put("token", jwt); return map; } }
Create a controller: Create a user in the controller Create an account Create a new 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<String, String> getToken(@RequestParam Map<String, String> map) { String username = map.get("username"); String password = map.get("password"); System.out.println(username + ' ' + password); return loginService.getToken(username, password); } }
2. Configure InforService class
Returns user information based on the token.
Create an interface: Create a user under service Create an account Create an interface InfoService
package com.kob.backend.service.user.account; import java.util.Map; public interface InfoService { public Map<String, String> getInfo(); }
Create an implementation class: create a user under impl under service, create an account, create a new implementation class 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 { /** * Return user information according to the token * @return map Stored information */ @Override public Map<String, String> getInfo() { UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); UserDetailsImpl loginUser = (UserDetailsImpl) authentication.getPrincipal(); User user = loginUser.getUser(); Map<String, String> 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; } }
Create a controller: create a user in the controller, create an account, and create an 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<String, String> getInfo() { return infoService.getInfo(); } }
3. Configure the RegisterService class
Registered account
Create an interface: create a user under service, create an account, and create an interface RegisterService
package com.kob.backend.service.user.account; import java.util.Map; public interface RegisterService { public Map<String, String> register(String username, String password, String confirmedPassword); }
Create an implementation class: create a user under impl under service, create an account, create a new implementation class, 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<String, String> register(String username, String password, String confirmedPassword) { Map<String, String> map = new HashMap<>(); if (username == null) { map.put("error_message", "User name cannot be empty"); return map; } if (password == null || confirmedPassword == null) { map.put("error_message", "Password cannot be empty"); return map; } //Remove first and last white space characters username = username.trim(); if (username.length() == 0) { map.put("error_message", "User name cannot be empty"); return map; } if (password.length() == 0 || confirmedPassword.length() == 0) { map.put("error_message", "Password cannot be empty"); return map; } if (username.length() > 100) { map.put("error_message", "The user name length cannot be greater than 100"); return map; } if (password.length() > 100 || confirmedPassword.length() > 100) { map.put("error_message", "Password cannot be greater than 100"); return map; } if (!password.equals(confirmedPassword)) { map.put("error_message", "The passwords entered twice are inconsistent"); return map; } //Query whether the user name is duplicate QueryWrapper<User> queryWrapper = new QueryWrapper<User>(); queryWrapper.eq("username", username); List<User> users = userMapper.selectList(queryWrapper); if (!users.isEmpty()) { map.put("error_message", "User name already exists"); return map; } // Add a new user String encodedPassword = passwordEncoder.encode(password); //Enter your own picture address String photo = "******************************"; User user = new User(null, username, encodedPassword, photo); userMapper.insert(user); map.put("error_message", "success"); return map; } }
Create a controller: create a user in the controller, create an account, and create a new 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<String, String> register(@RequestParam Map<String, String> map) { String username = map.get("username"); String password = map.get("password"); String confirmedPassword = map.get("confirmedPassword"); return registerService.register(username, password, confirmedPassword); } }
3.2 Debugging interface API
Verify user login:
In APP Written in vue:
Note: The Authorization: "Bearer" here has spaces, and the token is the token of your browser. You need to change the token.
<template> <NavBar></NavBar> <router-view></router-view> </template> <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() { // Test 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); } }); // Test 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); } }); // Test 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>
The success interface is as follows:
4. Implement the front-end login and registration interface
1. Implement the front-end style of two pages - login and registration:
from bootstrap Go up and find the right style:
for instance:
Style:
<div class="container"> <div class="row row-cols-2"> <div class="col">Column</div> <div class="col">Column</div> </div> </div>
Form:
<div class="mb-3"> <label for="exampleFormControlInput1" class="form-label">Email address</label> <input type="email" class="form-control" id="exampleFormControlInput1" placeholder="name@example.com"> </div> <div class="mb-3"> <label for="exampleFormControlTextarea1" class="form-label">Example textarea</label> <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea> </div>
Submit button
<button type="button" class="btn btn-primary">Primary</button>
To create a page:
Create a user in the views directory, and create two new files, UserAccountLoginView Vue and UserAccountRegisterView vue .
Implement UserAccountRegisterView Vue page
<template> <ContentField> register </ContentField> </template> <script> import ContentField from '../../../components/ContentField.vue' export default { components: { ContentField } } </script> <style scoped> </style>
Implement UserAccountLoginView Vue page
Basic login page
<template> <ContentField> <div class="row justify-content-md-center"> <div class="col-3"> <form> <div class="mb-3"> <label for="username" class="form-label">user name</label> <input v-model="username" type="text" class="form-control" id="username" placeholder="enter one user name"> </div> <div class="mb-3"> <label for="password" class="form-label">password</label> <input v-model="password" type="password" class="form-control" id="password" placeholder="Please input a password"> </div> <div class="error-message">{{ error_message }}</div> <button type="submit" class="btn btn-primary">Submit</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>
The effect is as follows:
2. Add the path to index.js in the router directory
Modify 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
3. Store user information in user.js under the store
Create user.js in the store
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: { } }
4 Add the user to the global module
index.js in the store
import { createStore } from 'vuex' import ModuleUser from './user' export default createStore({ state: { }, getters: { }, mutations: { }, actions: { }, modules: { user: ModuleUser, } })
5. Add auxiliary function login
User in the store Js modification.
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: { } }
6. In UserAccountLoginView Implemented in vue
<script> 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(''); //Trigger function 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() { //Obtain user information after successful login store.dispatch("getinfo", { success() { router.push({ name: 'home' }); console.log(store.state.user); } }) }, error() { error_message.value = "User name or password error "; } */ }) } return { username, password, error_message, login, } } } </script>
7. Bind content and variables
<form @submit.prevent="login"> <div class="mb-3"> <label for="username" class="form-label">user name</label> <input v-model="username" type="text" class="form-control" id="username" placeholder="enter one user name"> </div> <div class="mb-3"> <label for="password" class="form-label">password</label> <input v-model="password" type="password" class="form-control" id="password" placeholder="Please input a password"> </div> <div class="error-message">{{ error_message }}</div> <button type="submit" class="btn btn-primary">Submit</button> </form>
8. Test on the login interface
Enter the user name and password to obtain the token.
9. The user name and password are entered correctly. Click Submit to jump to the main page
In UserAccountLoginView Implemented in vue
<script> 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(''); //Trigger function const login = () => { error_message.value = ""; store.dispatch("login", { username: username.value, password: password.value, success() { //Jump to the main page after success router.push({name: 'home'}); }, error() { error_message.value = "User name or password error"; } /* success() { //Obtain user information after successful login store.dispatch("getinfo", { success() { router.push({ name: 'home' }); console.log(store.state.user); } }) }, error() { error_message.value = "User name or password error "; } */ }) } return { username, password, error_message, login, } } } </script>
10. Obtain user information after successful login
At user Add auxiliary functions in 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, }, //The user is updated on success. success(resp) { if (resp.error_message === "success") { // context.commit("updateToken", resp.token); // data.success(resp); context.commit("updateUser", { ...resp, is_login: true, }); } else { data.error(resp); } }, error(resp) { data.error(resp); } }); }, logout(context) { context.commit("logout"); } }, modules: { } }
Modify UserAccountLoginView.vue
<script> 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(''); //Trigger function const login = () => { error_message.value = ""; store.dispatch("login", { username: username.value, password: password.value, success() { //Obtain user information after successful login store.dispatch("getinfo", { success(resp) { router.push({ name: 'home' }); console.log(store.state.user); } }) }, error() { error_message.value = "User name or password error"; } }) } return { username, password, error_message, login, } } } </script>
The success interface is as follows:
11. Return the results to the personal information in the upper right corner – modify the navigation bar
Modify NavBar.vue
<template> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <div class="container"> <router-link class="navbar-brand" :to="{name: 'home'}">King Of Bots</router-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'}">Duel War</router-link> </li> <li class="nav-item"> <router-link :class="route_name == 'record_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'record_index'}">Matchmaking list</router-link> </li> <li class="nav-item"> <router-link :class="route_name == 'ranklist_index' ? 'nav-link active' : 'nav-link'" :to="{name: 'ranklist_index'}">Ranking List</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'}">my Bot</router-link> </li> <li><hr class="dropdown-divider"></li> <li><a class="dropdown-item" href="#"@ click=" logout ">Exit</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"> Sign in </router-link> </li> <li class="nav-item"> <router-link class="nav-link" :to="{name: 'user_account_register'}" role="button"> register </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>
12. Log out
user.js Add auxiliary function
mutations: { logout(state) { state.id = ""; state.username = ""; state.photo = ""; state.token = ""; state.is_login = false; } }, actions: { logout(context) { context.commit("logout"); } },
At navabar Vue add component
<li><a class="dropdown-item" href="#"@ click=" logout ">Exit</a></li> <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>
Code Address
4.2 Realization of Registration and Login Module – King of Bots