spring security+jwt 登录认证

  • 1.综述
  • 2.版本与环境
  • 3.架构
  • 4.数据库认证逻辑图
  • 5.案例 security+jwt
    • 5.1引入依赖
    • 5.2新建工具类
    • 5.2新建组件类
    • 5.3新建配置类
    • 5.4新建过滤类
  • 6.登录访问,接口访问
  • 7.项目地址

1.综述

Spring 是非常流行和成功的 Java 应用开发框架,Spring Security 正是 Spring 家族中的
成员。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方
案( 用户认证与用户授权)。

2.版本与环境

idea2022
maven3.6+
jdk1.8
security 5.7.2

3.架构

4.数据库认证逻辑图

5.案例 security+jwt

5.1引入依赖

   <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><!--缺少此jar包,导致@Mapper注解无效--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId></dependency>

5.2新建工具类

JwtUtil

package com.gz.security.utils;import com.gz.security.config.JwtConfig;
import com.gz.security.constant.Constant;
import com.gz.security.pojo.auth.AccessToken;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import cn.hutool.core.date.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;/*** @author: GZ* @description: JWT 工具类** <p>* 一个完整的JwtToken由三部分组成:头部+负载信息+签名* header 存放JwtToken签名的算法 | token的类型:{"alg": "HS512","typ": "JWT"}* payload 主要存放用户名、创建时间、生成时间:{"sub":"RenHe","created":1489079981393,"exp":1489684781}* signature 生成算法:HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret)* <p>*/
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class JwtUtil {private final JwtConfig jwtConfig;/*** 从request中获取token** @param request* @return*/public String getToken(HttpServletRequest request) {return request.getHeader(Constant.REQUEST_HEADER);}/*** 生成token** @param subject* @return*/public AccessToken generateToken(String subject) {final Date now = new Date();Long expired = Long.valueOf(jwtConfig.getExpiredTime());final Date expiredTime = new Date(now.getTime() + expired * 1000);String token = Constant.TOKEN_PREFIX + Jwts.builder().setSubject(subject).setIssuedAt(now).setExpiration(expiredTime).signWith(SignatureAlgorithm.HS512, jwtConfig.getApiSecretKey()).compact();return AccessToken.builder().loginAccount(subject).falconToken(token).expiredTime(expiredTime).build();}/*** 验证token** @param token    token from client* @param username user details from database*/public boolean validateToken(String token, String username) {Claims claims = getClaimsFromToken(token);return claims.getSubject().equals(username) && !isTokenExpired(claims);}/*** 刷新token** @param oldToken token with tokenHead*/public AccessToken refreshToken(String oldToken) {String token = oldToken.substring(Constant.TOKEN_PREFIX.length());Claims claims = getClaimsFromToken(token);if (tokenRefreshJustBefore(claims)) {return AccessToken.builder().loginAccount(claims.getSubject()).falconToken(oldToken).expiredTime(claims.getExpiration()).build();} else {return generateToken(claims.getSubject());}}/*** 检查token在指定时间内是否被刷新*/private boolean tokenRefreshJustBefore(Claims claims) {Date refreshDate = new Date();if (refreshDate.after(claims.getExpiration()) && refreshDate.before(DateUtil.offsetSecond(claims.getExpiration(), 1800))) {return true;}return false;}/*** 从token中获取Claims** @param token* @return*/private Claims getClaimsFromToken(String token) {Claims claims = null;try {claims = Jwts.parser().setSigningKey(jwtConfig.getApiSecretKey()).parseClaimsJws(token).getBody();} catch (Exception e) {log.error("JWT de-resolve fail, token expired or incorrect, token: {}", token);}return claims;}/*** 从token中获取用户信息*/public String getSubjectFromToken(String token) {Claims claims = getClaimsFromToken(token);if (Objects.nonNull(claims)) {return claims.getSubject();} else {return null;}}/*** 检查是否过期*/private boolean isTokenExpired(Claims claims) {return claims.getExpiration().before(new Date());}}

AuthUtil

package com.gz.security.utils;import com.gz.security.constant.Constant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;/*** @author: GZ* @description: 授权工具类*/
@Slf4j
public class AuthUtil {/*** Retrieve login account from token** @param authToken* @param jwtProvider* @return*/public static String getLoginAccountFromToken(String authToken, JwtUtil jwtProvider) {if (StringUtils.isEmpty(authToken) || !authToken.startsWith(Constant.TOKEN_PREFIX)) {log.info("token is empty or not start with Bearer");return StringUtils.EMPTY;}// 移除token前缀 (Bearer )authToken = authToken.substring(Constant.TOKEN_PREFIX.length());// 从token获取登录账户String loginAccount = jwtProvider.getSubjectFromToken(authToken);return loginAccount;}}

5.2新建组件类

CustomAccessDeniedHandler

package com.gz.security.component;import com.gz.security.pojo.auth.JsonAuthentication;
import com.gz.security.pojo.response.WebResponseBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author: GZ* @description: 禁止访问处理 403*/
@Component
public class CustomAccessDeniedHandler extends JsonAuthentication implements AccessDeniedHandler {private static final Log logger = LogFactory.getLog(CustomAccessDeniedHandler.class);@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e)throws IOException {logger.info("Pre-authenticated entry point called. Access denied");response.setStatus(HttpServletResponse.SC_FORBIDDEN);this.writeJSON(response, WebResponseBuilder.fail("403","禁止访问"));}
}

CustomAuthenticationEntryPoint

package com.gz.security.component;import com.gz.security.pojo.auth.JsonAuthentication;
import com.gz.security.pojo.response.WebResponseBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author: GZ* @description: 未授权处理 401 用来解决匿名用户访问无权限资源时的异常*/
@Component
public class CustomAuthenticationEntryPoint extends JsonAuthentication implements AuthenticationEntryPoint {private static final Log logger = LogFactory.getLog(CustomAuthenticationEntryPoint.class);@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2)throws IOException {logger.info("Authenticated entry point called. Unauthorized");response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);this.writeJSON(response, WebResponseBuilder.fail("401","未授权"));}
}

CustomAuthenticationFailureHandler


package com.gz.security.component;import com.gz.security.pojo.auth.JsonAuthentication;
import com.gz.security.pojo.response.WebResponseBuilder;
import lombok.extern.slf4j.Slf4j;import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author GuoZhong* @description 认证失败服务出口* @date 2022/10/11 10:03*/@Slf4j
@Component
public class CustomAuthenticationFailureHandler  extends JsonAuthentication implements AuthenticationFailureHandler {@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {response.setStatus(HttpServletResponse.SC_OK);// 处理异常if (exception instanceof InternalAuthenticationServiceException) {this.writeJSON(response,WebResponseBuilder.fail("500",exception.getMessage()));} else if (exception instanceof BadCredentialsException) {this.writeJSON(response,WebResponseBuilder.fail("500",exception.getMessage()));} else {// 输出错误信息this.writeJSON(response,WebResponseBuilder.fail("500",exception.getMessage()));}}
}

CustomAuthenticationProvider

package com.gz.security.component;import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;/*** @author: GZ* @date: 2021/9/6 11:11* @description: 登录身份验证*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CustomAuthenticationProvider implements AuthenticationProvider {private final UserDetailsService userDetailsService;@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {String username = (String) authentication.getPrincipal();String password = (String) authentication.getCredentials();User user=null;try {user  = (User) userDetailsService.loadUserByUsername(username);} catch (UsernameNotFoundException e) {throw new InternalAuthenticationServiceException("用户不存在");}return new UsernamePasswordAuthenticationToken(user, password, user.getAuthorities());}@Overridepublic boolean supports(Class<?> authentication) {return authentication.equals(UsernamePasswordAuthenticationToken.class);}}

CustomAuthenticationSuccessHandler


package com.gz.security.component;import com.gz.security.config.RedisConfig;
import com.gz.security.constant.RedisKey;import com.gz.security.pojo.auth.JsonAuthentication;
import com.gz.security.pojo.response.WebResponseBuilder;
import com.gz.security.utils.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;/*** @author GuoZhong* @description 登录成功出口* @date 2022/10/11 10:07*/@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CustomAuthenticationSuccessHandler extends JsonAuthentication implements AuthenticationSuccessHandler {private final JwtUtil jwtUtil;private final RedisTemplate redisTemplate;private final RedisConfig redisConfig;@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException {response.setStatus(HttpServletResponse.SC_OK);User loginAccount = (User) authentication.getPrincipal();String username = loginAccount.getUsername();//存储用户信息,设置过期时间redisTemplate.opsForValue().set(RedisKey.getLoginAccountKey(username),loginAccount,Long.valueOf(redisConfig.getExpiredTime()),TimeUnit.MINUTES);// 输出正确响应信息this.writeJSON(response, WebResponseBuilder.success(jwtUtil.generateToken(username)));}}

CustomLogoutSuccessHandler

package com.gz.security.component;import com.gz.security.constant.RedisKey;
import com.gz.security.pojo.auth.JsonAuthentication;
import com.gz.security.pojo.response.WebResponseBuilder;
import com.gz.security.utils.AuthUtil;
import com.gz.security.utils.JwtUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author: RenHe* @date: 2021/9/6 11:11* @description: 登出成功处理*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CustomLogoutSuccessHandler extends JsonAuthentication implements LogoutSuccessHandler {private final JwtUtil jwtUtil;private final RedisTemplate redisTemplate;@Overridepublic void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException {String authToken = jwtUtil.getToken(request);String loginAccount = AuthUtil.getLoginAccountFromToken(authToken, jwtUtil);redisTemplate.delete(RedisKey.getLoginAccountKey(loginAccount));response.setStatus(HttpServletResponse.SC_OK);this.writeJSON(response, WebResponseBuilder.success("退出成功"));}
}

5.3新建配置类

SecurityConfig

package com.gz.security.config;import com.gz.security.component.*;
import com.gz.security.filter.JwtAuthenticationTokenFilter;
import lombok.RequiredArgsConstructor;
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.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;/*** @author GZ* security核心配置类*/
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {/*** 默认授权白名单*/private static final String DEFAULT_AUTH_WHITE_LIST = "/login";/*** 用户名*/private static final String USERNAME_PARAMETER = "username";/*** 密码*/private static final String PASSWORD_PARAMETER = "password";/*** 登录*/private static final String LOGIN = "/login";/*** 登出*/private static final String LOGOUT = "/logout";private final CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;private final CustomAuthenticationFailureHandler customAuthenticationFailureHandler;private final CustomAuthenticationEntryPoint authenticationEntryPoint;private final CustomAccessDeniedHandler accessDeniedHandler;private final JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;private final LogoutSuccessHandler customLogoutSuccessHandler;/*** 安全认证过滤链配置*/@Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.formLogin().loginProcessingUrl(LOGIN).usernameParameter(USERNAME_PARAMETER).passwordParameter(PASSWORD_PARAMETER)//成功出口.successHandler(customAuthenticationSuccessHandler)//失败出口.failureHandler(customAuthenticationFailureHandler).and().logout().logoutUrl(LOGOUT).clearAuthentication(true)//退出出口.logoutSuccessHandler(customLogoutSuccessHandler).and().authorizeRequests()// 放行所有OPTIONS请求.antMatchers(HttpMethod.OPTIONS).permitAll()// 放行白名单地址.antMatchers(DEFAULT_AUTH_WHITE_LIST).permitAll().and()// 打开Spring Security的跨域,需要新增配置文件.cors().and()// 关闭CSRF.csrf().disable()// 添加未登录与权限不足异常处理器.exceptionHandling()//未授权.authenticationEntryPoint(authenticationEntryPoint)//禁止访问.accessDeniedHandler(accessDeniedHandler)// 将自定义的JWT过滤器放到过滤链中.and().addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)// 关闭Session机制.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);return http.build();}/*** 认证管理器*/@Beanpublic AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {return authenticationConfiguration.getAuthenticationManager();}/*** 加密方式*/@Beanpublic PasswordEncoder passwordEncoder() {return PasswordEncoderFactories.createDelegatingPasswordEncoder();}}

JwtConfig

package com.gz.security.config;import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** @author: GZ* @description: JWT配置*/
@Configuration
@ConfigurationProperties("jwt")
@Data
@ToString
public class JwtConfig {/*** 密钥*/private String apiSecretKey = "JWT_SECRET_KEY";/*** 过期时间 默认7天*/private String expiredTime = "10080";}

CorsConfig


package com.gz.security.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;
import java.util.ArrayList;
import java.util.List;/*** @author GuoZhong* @description 跨域请求配置*/@Configuration
public class CorsConfig {/*** 可跨域请求** @return*/@Beanpublic CorsFilter corsFilter() {final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();final CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.setAllowCredentials(true);List<String> allowedOriginPatterns = new ArrayList<>();allowedOriginPatterns.add("*");corsConfiguration.addAllowedOrigin("*");corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);return new CorsFilter(urlBasedCorsConfigurationSource);}}

AuthenticationConfig

package com.gz.security.config;import com.gz.security.component.CustomAuthenticationProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;/*** @author GuoZhong* @description Authentication 全局配置* @date 2022/10/16 12:35*/
@Configuration
@RequiredArgsConstructor
public class AuthenticationConfig extends GlobalAuthenticationConfigurerAdapter {private final CustomAuthenticationProvider customAuthenticationProvider;private final UserDetailsService userDetailsService;@Overridepublic void init(AuthenticationManagerBuilder auth) throws Exception {auth.eraseCredentials(false).authenticationProvider(customAuthenticationProvider).userDetailsService(userDetailsService);}
}

5.4新建过滤类

JwtAuthenticationTokenFilter

package com.gz.security.filter;import com.gz.security.constant.Constant;
import com.gz.security.constant.RedisKey;
import com.gz.security.pojo.auth.UserInfo;
import com.gz.security.utils.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;/*** @author GZ*  JWT 登录过滤器*/
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {private final JwtUtil jwtUtil;private final RedisTemplate redisTemplate;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, javax.servlet.FilterChain chain)throws ServletException, IOException {log.info("JWT filter verification token from request header to  auto login start");// 从请求头获取授权信息String authToken = jwtUtil.getToken(request);if (StringUtils.isEmpty(authToken) || !authToken.startsWith(Constant.TOKEN_PREFIX)) {log.info("Token is empty or not start with Bearer");chain.doFilter(request, response);return;}// 移除token前缀'Bearer 'authToken = authToken.substring(Constant.TOKEN_PREFIX.length());// 从token中获取登录用户String username = jwtUtil.getSubjectFromToken(authToken);if (StringUtils.isEmpty(username)) {log.info("Login account is empty");chain.doFilter(request, response);return;}// 从缓存中获取用户信息UserInfo userInfo = (UserInfo) redisTemplate.opsForValue().get(RedisKey.getLoginAccountKey(username));// 验证token是否过期if (Objects.isNull(userInfo)) {log.info("Token is invalid");chain.doFilter(request, response);return;}// TODO 校验网关 后期放到网关去校验if (!jwtUtil.validateToken(authToken, userInfo.getUsername())) {log.info("Token is invalid");chain.doFilter(request, response);return;}// 创建authenticationUsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userInfo, userInfo.getPassword(),null);// 设置authentication到contextSecurityContextHolder.getContext().setAuthentication(authentication);chain.doFilter(request, response);log.info("JWT filter verification token from request header to  auto login successfully end, user : {}", userInfo);}}

6.登录访问,接口访问


7.项目地址

https://gitee.com/GZ-jelly/gz-login-spring-boot-starter.git

spring security+jwt 登录认证相关推荐

  1. Spring Security + JWT 实现认证和授权

    整体流程 用户登录成功后,服务端返回 jwt token 给客户端.token 中包含用户名,失效时间等信息.客户端保存 token,服务端不进行存储.客户端每次发送请求的时候,带上 token,服务 ...

  2. spring boot +spring security + jwt 实现认证模块

    我在使用spring进行开发时,通常是使用 aop+jwt 模式来对调用者身份进行确认.前几天接触到一个开源商城源码(github地址)里面使用spring security +jwt 来进行权限的验 ...

  3. Spring Security进行登录认证和授权

    一.Spring Security内部认证流程 用户首次登录提交用户名和密码后spring security 的UsernamePasswordAuthenticationFilter把用户名密码封装 ...

  4. SpringBoot+Security+Jwt登录认证与权限控制(一)

    一.相关技术 1. Maven 项目管理工具 2. MybatisPlus 3. SpringBoot 2.7.0 4. Security 安全框架 5. Jwt 6. easy-captcha 验证 ...

  5. 清晰搞懂Spring Security的登录认证

    文章目录 前言 1.简介 2.登录认证 2.1.过滤器链 2.2.认证流程 2.3.大思路分析 3.撸袖开干 3.1.环境搭建 3.1.1.数据库 3.1.2.项目搭建 3.1.3.工具类.部分配置类 ...

  6. springboot jwt token前后端分离_基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目...

    一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...

  7. 自定义request_Spring Security 自定义登录认证(二)

    一.前言 本篇文章将讲述Spring Security自定义登录认证校验用户名.密码,自定义密码加密方式,以及在前后端分离的情况下认证失败或成功处理返回json格式数据 温馨小提示:Spring Se ...

  8. 超实用,Spring Security+JWT+Vue实现一个前后端分离无状态认证Demo

    作者: 陕西颜值扛把子 https://zhuanlan.zhihu.com/p/95560389 精彩推荐 一百期Java面试题汇总 SpringBoot内容聚合 IntelliJ IDEA内容聚合 ...

  9. Spring Boot + Spring Security + JWT + 微信小程序登录

    Spring Boot + Spring Security + JWT + 微信小程序登录整合教程 参考文章 文章目录 整合思想 整合步骤 1. AuthenticationToken 2. Auth ...

最新文章

  1. java for循环 暂停_类中的2个for循环不想在第一次迭代后迭代c [暂停]
  2. springboot常用配置
  3. Java9发布回顾Java 8的十大新特性
  4. windows命令提示符下输入net start/stop mysql发生系统错误5,拒绝访问的解决方法
  5. perl anyevent socket监控web日志client
  6. pdo 错误 php,多语句查询中的PHP PDO错误
  7. opencv ppt效果_opencv几何图形画法
  8. Android 解压zip文件
  9. oracle如何查看实例用户,oracle 如何显示当前执行的用户和操作实例
  10. L1-008. 求整数段和-PAT团体程序设计天梯赛GPLT
  11. 后台管理系统下载excel文件
  12. Lwip协议详解(基于Lwip 2.1.0)-内存管理
  13. 睡眠监测中的一些术语和指标(AASM)
  14. 如何实现两台windows电脑便签同步共享
  15. 怎样给word插入页码,点击进来有惊喜
  16. 精益创业实战 - 第5章 开始实验
  17. 基于SSM的手机商城-JAVA【数据库设计、源码、开题报告】
  18. iOS_3DTouch使用
  19. UnicodeEncodeError: 'gbk' codec can't encode character '\uXXX' in position
  20. c# 调整图片分辨率

热门文章

  1. HHC6003: Error: The file Itircl.dll has not been
  2. 极简的wrk安装和使用教程
  3. 排序---小白鼠排队
  4. 华为p50鸿蒙系统手机价格,华为P50系列屏幕、镜头、芯片、价格全曝光,预装鸿蒙系统?...
  5. 西工大机考《 催化剂工程》大作业网考
  6. 腾讯QQ大数据:BI方法论-数据体系建设之路
  7. Linux常用工具的使用
  8. Nacos 2.1.0 正式发布!堪称最强!
  9. 【干货】麦肯锡七步成诗解决问题方法最新原版课件.pdf(附下载链接)
  10. 上传本地.xlsx(.xls)文件,实现页面表格数据预览