赞
踩
JWT全称是JSON Web Token,如果从字面上理解感觉是基于JSON格式用于网络传输的令牌。实际上,JWT是一种紧凑的Claims声明格式,旨在用于空间受限的环境进行传输,常见的场景如HTTP授权请求头参数和URI查询参数。JWT会把Claims转换成JSON格式,而这个JSON内容将会应用为JWS结构的有效载荷或者应用为JWE结构的(加密处理后的)原始字符串,通过消息认证码(Message Authentication Code或者简称MAC)和/或者加密操作对Claims进行数字签名或者完整性保护。
- <!-- hutool 依赖 -->
- <dependency>
- <groupId>cn.hutool</groupId>
- <artifactId>hutool-all</artifactId>
- <version>5.8.16</version>
- </dependency>
这里就不过多写了,依旧是跟上一边的文章一样

- package com.aaa.filter;
-
- import cn.hutool.jwt.JWT;
- import cn.hutool.jwt.JWTUtil;
- import com.aaa.until.ResponseMsg;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.apache.commons.lang3.ArrayUtils;
- 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 {
-
-
- /**
- * 重写的doFilterInternal方法
- * 解析token并验证用户信息
- * 如果验证成功,则保存用户信息并放行
- * 如果验证失败,则返回错误信息
- * 如果token为空且请求路径不在白名单中,则返回错误信息
- */
- @Override
- protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
- // 白名单路径
- String[] whitename = {"/login"};
- // 获取请求头中的token
- String token = request.getHeader("token");
- // 如果token不为空
- if (StringUtils.isNotBlank(token)) {
- // 验证token是否有效
- boolean verify = JWTUtil.verify(token, "user".getBytes());
- // 如果验证通过
- if (verify) {
- // 解析token,获取用户名和资源信息
- JWT jwt = JWTUtil.parseToken(token);
- String username = (String) jwt.getPayload("username");
- List<String> resources = (List<String>) jwt.getPayload("resources");
-
- // 将资源信息转换为SimpleGrantedAuthority列表
- List<SimpleGrantedAuthority> resourceList = resources.stream().map(res -> new SimpleGrantedAuthority(res)).collect(Collectors.toList());
-
- // 保存用户信息
- UsernamePasswordAuthenticationToken userPwdToken = new UsernamePasswordAuthenticationToken(username, null, resourceList);
- SecurityContextHolder.getContext().setAuthentication(userPwdToken);
-
- // 放行
- filterChain.doFilter(request, response);
- } else {
- // 验证失败,返回错误信息
- ResponseMsg responseMsg = new ResponseMsg(401, "没有登陆", null);
- printJsonData(response, responseMsg);
- }
- } else {
- // 如果token为空,检查请求路径是否在白名单中
- String requestURI = request.getRequestURI();
-
- // 如果在白名单中,放行
- if (ArrayUtils.contains(whitename, requestURI)) {
- filterChain.doFilter(request, response);
- } else {
- // 如果不在白名单中,返回错误信息
- ResponseMsg responseMsg = new ResponseMsg(401, "没有登陆", null);
- printJsonData(response, responseMsg);
- }
- }
- }
-
- public void printJsonData(HttpServletResponse response, ResponseMsg responseMsg) {
- try {
- response.setContentType("application/json;charset=utf8"); // 设置响应内容类型为JSON,并指定编码为UTF-8
- ObjectMapper objectMapper = new ObjectMapper();
- String json = objectMapper.writeValueAsString(responseMsg); // 使用ObjectMapper将ResponseMsg对象转化为JSON字符串
- PrintWriter writer = response.getWriter();
- writer.print(json); // 将JSON字符串写入响应输出流
- writer.flush();//刷新
- writer.close();//关闭
- } catch (Exception e) {
- e.printStackTrace(); // 打印异常堆栈信息
- }
- }
- }

- package com.aaa.config;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.cors.CorsConfiguration;
- import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
- import org.springframework.web.filter.CorsFilter;
-
- @Configuration
- public class CrossConfig {
- @Bean
- public CorsFilter corsFilter() {
- final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- final CorsConfiguration corsConfiguration = new CorsConfiguration();
- //corsConfiguration.setAllowCredentials(true);允许携带cookie
- corsConfiguration.addAllowedHeader("*"); // 允许所有的头
- corsConfiguration.addAllowedOrigin("*"); // 允许所有的请求源
- corsConfiguration.addAllowedMethod("*"); // 所欲的方法 get post delete put
- source.registerCorsConfiguration("/**", corsConfiguration); // 所有的路径都允许跨域
- return new CorsFilter(source);
- }
-
- }

- package com.aaa.config;
-
- import cn.hutool.jwt.JWTUtil;
- import com.aaa.filter.JWTFilter;
- import com.aaa.until.ResponseMsg;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
- import org.springframework.security.config.annotation.web.builders.HttpSecurity;
- import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.userdetails.UserDetailsService;
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
- import org.springframework.security.crypto.password.PasswordEncoder;
- import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
-
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletResponse;
- import java.io.PrintWriter;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import java.util.stream.Collectors;
-
-
- @Configuration
- public class SecurityConfig extends WebSecurityConfigurerAdapter {
- @Resource
- protected UserDetailsService userDetailsService;
- @Bean
- public PasswordEncoder passwordEncoder(){
- return new BCryptPasswordEncoder();
- }
- @Resource
- public JWTFilter jwtFilter;
-
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- //.usernameParameter("username")//登陆账号
- //.passwordParameter("userpassword");//登陆密码
- //.defaultSuccessUrl("/test");//登陆成功的跳转路径
-
-
- // 配置登录页面和登录处理路径
- http.formLogin().loginPage("/login.html")//路径前面必须加 /
- .loginProcessingUrl("/login")//跟提交的路径一样
- // 登录成功的处理逻辑
- .successHandler((request, response, authentication) ->{
- Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();//获取资源信息
- List<String> resources = authorities.stream().map(auth -> auth.getAuthority()).collect(Collectors.toList());//转为stream流变成list
- Map map = new HashMap<>();
- map.put("username",authentication.getName());
- map.put("resources",resources);
- //生成token
- String token = JWTUtil.createToken(map, "user".getBytes());
- ResponseMsg responseMsg = new ResponseMsg(200,"登陆成功",token);
- //响应返回信息
- printJsonData(response,responseMsg);
- })
- // 登录失败的处理逻辑
- .failureHandler((request, response, exception)->{
- ResponseMsg responseMsg = new ResponseMsg(400,"验证失败");
- printJsonData(response,responseMsg);
- });
-
- // 配置权限不允许的处理逻辑
- http.exceptionHandling().accessDeniedHandler((request, response, accessDeniedException) -> {
- ResponseMsg responseMsg = new ResponseMsg(403,"权限不允许",null);
- printJsonData(response,responseMsg);
- });
-
- // 配置不需要验证的路径
- http.authorizeRequests().antMatchers("/login.html", "login").permitAll();//不用验证
- //http.authorizeRequests().antMatchers("/test").hasRole("test");//必须有哪个权限才能访问
- //http.authorizeRequests().antMatchers("/test").hasAnyAuthority("resource");//必须有哪个资源才能访问
-
- // 配置其他路径需要验证
- http.authorizeRequests().anyRequest().authenticated();
-
- // 添加JWT过滤器
- http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
-
- //关闭csrf保护
- http.csrf().disable();
-
- // 配置跨域
- http.cors();
-
- }
-
- @Override
- protected void configure(AuthenticationManagerBuilder auth) throws Exception {
- auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
- }
-
-
- public void printJsonData(HttpServletResponse response, ResponseMsg responseMsg) {
-
- try {
- response.setContentType("application/json;charset=utf8"); // json格式 编码是中文
- ObjectMapper objectMapper = new ObjectMapper();
- String s = objectMapper.writeValueAsString(responseMsg);// 使用ObjectMapper将result转化json为字符串
- PrintWriter writer = response.getWriter();
- writer.print(s);
- writer.flush();
- writer.close();
- }catch (Exception e){
- e.printStackTrace();
-
- }
- }
- }

也是跟上一篇的笔记一样
不要忘了在路由下添加login页面

- <template>
- <div>
- <el-form style="width: 400px ;margin: auto auto" :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
- <el-form-item label="名字" prop="username">
- <el-input type="text" v-model="ruleForm.username" autocomplete="off"></el-input>
- </el-form-item>
- <el-form-item label="密码" 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')">提交</el-button>
- <el-button @click="resetForm('ruleForm')">重置</el-button>
- </el-form-item>
- </el-form>
- </div>
- </template>
-
- <script>
- import qs from 'qs';
- export default {
- data() {
- return {
- ruleForm: {
- username: 'user000',//每次刷新页面都要重新输入账号密码,所以直接把账号密码写入进来了
- password: '123456',
- },
- rules: {
- username: [
- {required: true, message: '请输入账户', trigger: 'blur'}
- ],
- password: [
- {required: true, message: '请输入密码', trigger: 'blur'}
- ]
- }
- };
- },
- methods: {
- submitForm(formName) {
- this.$refs[formName].validate((valid) => {
- if (valid) {
- alert('验证成功,准备提交')
- this.$axios.post('/login',qs.stringify(this.ruleForm)).then(res=>{
- console.log(res)
- if (res.data.code == 200){
- console.log(res.data.data);
- //--------------------------------------------------------------
- sessionStorage.setItem("token",res.data.data)在sessionstorage中添加一个为token的数据
- //--------------------------------------------------------------
- location.href='/main';//成功访问main页面
- }else {
-
- }
- })
- //location.href='/main'
- } else {
- alert('验证失败');
- return false;
- }
- });
- },
- resetForm(formName) {
- this.$refs[formName].resetFields();
- }
- }
- }
- </script>

验证token是否存在,如果有的话就在请求头里面添加token
- // 请求拦截器
- instance.interceptors.request.use(config => {
- if (sessionStorage.getItem("token")){
- let token = sessionStorage.getItem("token");
- config.headers['token'] = token;
- }
- return config;
- }, error => {
- return Promise.reject(error);
- });
从前端页面输入账号向后端发送跨域请求,后端接受参数验证是否在数据库中存在,如果存在就去把用户在数据库中的角色权限和资源权限查出来,保存在Security中.登陆成功后就把用户的信息用JWTUtil.createToken()方法生成token,返回给前端,前端拿到token,前端再次向后端发起请求时携带token,后端识别,如果正确的话就放行,不正确就访问失败
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。