1. Create the vue front-end framework http://t.csdnimg.cn/jRcInhttp://t.csdnimg.cn/jRcIn
After creation, use the tool to open and download axios, element-ui
Then import axios and element-ui in the global configuration. I also have interceptors and paging plug-ins.
import axios from "axios"; import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; // For back-end projects http://localhost:8080 //axios sets a default path // Configure default values when creating an instance const instance = axios.create({ // Use a fake basic path when accessing the path baseURL: 'http://localhost:8080/' }); Vue.prototype.$axios = instance; Vue.use(ElementUI); instance.interceptors.response.use( response=> { // status code 500 if(response.data.code==500){ // Jump to the login component router.push({path:"/login"}); return; } // Data is returned directly to axios return response.data.t; }, error=> { // Status codes outside the 2xx range will trigger this function. // Do something with the response error return Promise.reject(error); }); // paging //------------------ //Introduce components import page from '@/views/util/page.vue'; //global component Vue.component("my-fenye",page); //---------------------
A front-end login page (with a background image to be changed)
<template> <div class="login-container"> <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="login-form"> <el-form-item label="username" prop="username"> <el-input type="text" v-model="ruleForm.username" autocomplete="off"></el-input> </el-form-item> <el-form-item label="Confirm password" prop="password"> <el-input type="password" v-model="ruleForm.password" autocomplete="off"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')">Submit</el-button> <el-button @click="resetForm('ruleForm')">Reset</el-button> </el-form-item> </el-form> </div> </template> <script> export default { data() { var checkName = (rule, value, callback) => { if (!value) { return callback(new Error('The name cannot be empty')); }else{ callback(); } }; var validatePass = (rule, value, callback) => { if (value === '') { callback(new Error('Please enter password')); } else { callback(); } }; return { ruleForm: { username: '', password: '', }, rules: { password: [ { validator: validatePass, trigger: 'blur' } ], username: [ { validator: checkName, trigger: 'blur' } ] } }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { alert('submit!'); } else { console.log('error submit!!'); } }); }, resetForm(formName) { this.$refs[formName].resetFields(); } } } </script> <style scoped> .login-form { width: 350px; margin: 160px auto; /* Top and bottom spacing 160px, left and right automatically centered*/ background-color: rgb(255, 255, 255,0.8); /* Transparent background color */ padding: 30px; border-radius: 20px; /* rounded corners */ } /* background */ .login-container { position: absolute; width: 100%; height: 100%; background: url("../assets/timg.png"); } /* title */ .login-title { color: #303133; text-align: center; } </style>
2. Obtain data
Download qs splicing data
Access backend data
This is a cross domain issue 302
Add http.cors() to the backend Security configuration;
I visited again and found that it still didn’t work. I found that there was a problem in the global configuration.
Returned If there is a problem with the data, just delete the data.t at the end.
now it’s right
1. Front-end and back-end authentication response data
@Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // Start configuring customized information http.formLogin() .loginPage("/login.html") .loginProcessingUrl("/userlogin")// The login path can be consistent with the login path in html or jsp .successHandler(new AuthenticationSuccessHandler() { /** * Authentication successful * @param request request object * @param response object of response * @param authentication authentication information * @throwsIOException * @throwsServletException */ @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { //Authentication successful //code 200 msg successful login t:null Result result = new Result(200,"Login successful",null); ObjectMapper objectMapper = new ObjectMapper(); //Use ObjectMapper to convert result into json string String s = objectMapper.writeValueAsString(result); //Response json data PrintWriter writer = response.getWriter(); writer.println(s); writer.flush();//Refresh writer.close();//Close } })//When performing front-end and back-end authentication, the authentication method is successful. ; http.authorizeRequests().antMatchers("userlogin").permitAll(); http.exceptionHandling().accessDeniedPage("/403.html"); // http.authorizeRequests().antMatchers("/test").hasRole("USER"); // http.authorizeRequests().antMatchers("/test").hasAuthority("testppp"); http.authorizeRequests().anyRequest().authenticated();//Except for paths that do not require authentication, all other paths require authentication http.csrf().disable(); // Turn off csrf protection http.cors();//Can cross domain } @Resource private UserDetailsService userDetailsService; @Bean public PasswordEncoder getPassword(){ return new BCryptPasswordEncoder(); } //Customize user information @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception{ auth.userDetailsService(userDetailsService).passwordEncoder(getPassword()); } }
Log in after setting up
Authentication successful (I messed up the code) add the following sentence
Authentication failed:
I encapsulated the same things in success and failure into a method
Test certification failed
A duplicate navigation issue occurred
The solution is as follows: put it under index.js
//Aiming at the problem of repeated navigation errors in the ElementUI navigation bar const originalPush = VueRouter.prototype.push VueRouter.prototype.push = function push(location) { return originalPush.call(this, location).catch(err => err) }
Because the interceptor is set and it is not 200, it is intercepted.
So we can only intercept the output here.
2. Visit the page
Create a main page and find one in element
<script setup> </script> <template> <el-container style="height: 500px; border: 1px solid #eee"> <el-aside width="200px" style="background-color: rgb(238, 241, 246)"> <el-menu :router="true"> <el-submenu index="1"> <template slot="title"><i class="el-icon-message"></i>Navigation 1</template> <el-menu-item-group> <el-menu-item index="/test">test</el-menu-item> <el-menu-item index="1-2">Option 2</el-menu-item> </el-menu-item-group> <el-menu-item-group> <el-menu-item index="1-3">Option 3</el-menu-item> </el-menu-item-group> <el-submenu index="1-4"> <template slot="title">Option 4</template> <el-menu-item index="1-4-1">Option 4-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="2"> <template slot="title"><i class="el-icon-menu"></i>Navigation 2</template> <el-menu-item-group> <template slot="title">Group 1</template> <el-menu-item index="2-1">Option 1</el-menu-item> <el-menu-item index="2-2">Option 2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="Group 2"> <el-menu-item index="2-3">Option 3</el-menu-item> </el-menu-item-group> <el-submenu index="2-4"> <template slot="title">Option 4</template> <el-menu-item index="2-4-1">Option 4-1</el-menu-item> </el-submenu> </el-submenu> <el-submenu index="3"> <template slot="title"><i class="el-icon-setting"></i>Navigation Three</template> <el-menu-item-group> <template slot="title">Group 1</template> <el-menu-item index="3-1">Option 1</el-menu-item> <el-menu-item index="3-2">Option 2</el-menu-item> </el-menu-item-group> <el-menu-item-group title="Group 2"> <el-menu-item index="3-3">Option 3</el-menu-item> </el-menu-item-group> <el-submenu index="3-4"> <template slot="title">Option 4</template> <el-menu-item index="3-4-1">Option 4-1</el-menu-item> </el-submenu> </el-submenu> </el-menu> </el-aside> <!----> <el-container> <el-header>Header</el-header> <el-main> <router-view></router-view> </el-main> <el-footer>Footer</el-footer> </el-container> </el-container> </template> <style scoped> .el-header { background-color: #B3C0D1; color: #333; line-height: 60px; } .el-aside { color: #333; } .el-header, .el-footer { background-color: #B3C0D1; color: #333; text-align: center; line-height: 60px; } .el-aside { background-color: #D3DCE6; color: #333; text-align: center; line-height: 200px; } .el-main { background-color: #E9EEF3; color: #333; text-align: center; line-height: 160px; } body > .el-container { margin-bottom: 40px; } .el-container:nth-child(5) .el-aside, .el-container:nth-child(6) .el-aside { line-height: 260px; } .el-container:nth-child(7) .el-aside { line-height: 320px; } </style>
Log in to main if successful
3. Store in cookie
In main.js
in cross-domain files
Then when I try to log in again, a cross-domain problem occurs.
solve!
Response data again
This is the data inside (the content inside is in the database)
3. Set permissions for user
403 No permission
三.jwt
Json web token (JWT) is an open standard based on JSON (RFC7519) for conveying claims between web application environments. The token is designed to be compact and secure, especially suitable for Single sign-on (SSO) scenario for distributed sites ==. JWT claims are generally used to pass authenticated user identity information between identity providers and service providers to facilitate obtaining resources from resource servers. You can also add some For additional declaration information necessary for other business logic, the token can also be used directly for authentication or encrypted.
Generate credential information
Header
The Header part is a JSON object describing the metadata of the JWT, which usually looks like the following.
{
“alg”: “HS256”,
“typ”: “JWT”
}
Payload
The Payload part is also a JSON object, == used to store the actual data that needs to be transferred==. JWT specifies 7 official fields for selection.
iss (issuer): issuer
exp (expiration time): expiration time
sub (subject): subject
aud (audience): audience
nbf (Not Before): effective time
iat (lssued At):Issuance time
jti (JWT ID): number
In addition to official fields, you can also define private fields in this section. Here is an example.
{
“sub”: “1234567890”,
“name” : “John Doe”,
“userid”:2
“admin”: true
}
Note that JWT is not encrypted by default and can be read by anyone, so do not put ==secret information== in this section. This JSON object must also be converted into a string using the Base64URL algorithm.
Signaretu
Signature is a signature of the first two parts to prevent data tampering.
First, you need to specify a secret. This key is only known to the server and cannot be leaked to the user. Then, use the ==signature algorithm specified in the Header (the default is HMAC SHA256)== to generate a signature according to the following formula.
HMACSHA256(
base64UrlEncode(header) + “.”” + base64UrlEncode(payload),
secret)
After calculating the signature, combine the three parts of Header, Payload, and Signature into a string, and separate each part with “dot” (.) before returning it to the user.
Add dependencies to the project
<!-- Add hutool dependency to the project --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.16</version> </dependency>
Generate certificate
The first and second parts are not encrypted and use the base64 encoding format. The original data can be obtained by reverse encoding through the website.
Base64 online encoding and decoding | Base64 encryption and decryption – Base64.us
Set time
After it is automatically generated, you can delete it automatically stored in the cookie.
Get a request connector
View stored tokens
Find the request header
Yes, but I can’t log in
Give him an interceptor
package com.aaa.config; import cn.hutool.jwt.JWT; import cn.hutool.jwt.JWTUtil; import com.aaa.util.Result; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.commons.lang3.StringUtils; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; 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; import java.io.PrintWriter; import java.util.List; import java.util.stream.Collectors; @Component public class JwtFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { //parse token /** * 1. Get token * There is analysis * No return json without authentication * 2.Yes * 2.1 Verification token */ // Get token String token = request.getHeader("token"); //tokent is not empty if (StringUtils.isNotBlank(token)){ //parse boolean verify = JWTUtil.verify(token, "pxy".getBytes()); if (verify){ //Verification passed //Get the user's name and password JWT jwt = JWTUtil.parseToken(token); String username = (String) jwt.getPayload("username"); List<String> resources = (List<String>) jwt.getPayload("resources"); List<SimpleGrantedAuthority> collect = resources.stream().map(s->new SimpleGrantedAuthority(s)).collect(Collectors.toList()); UsernamePasswordAuthenticationToken usertoken = new UsernamePasswordAuthenticationToken(username, null, collect); //Save user information SecurityContextHolder.getContext().setAuthentication(usertoken);//release filterChain.doFilter(request,response); } }else { Result result = new Result(401, "Not logged in", null); extracted(response,result); } } private void extracted(HttpServletResponse response, Result result) throws IOException { response.setContentType("application/json;charset=utf8"); ObjectMapper objectMapper = new ObjectMapper(); //Use ObjectMapper to convert result into json string String s = objectMapper.writeValueAsString(result); //Response json data PrintWriter writer = response.getWriter(); writer.println(s); writer.flush();//Refresh writer.close();//Close } }
JwtFilter: