当前位置: 首页 > news >正文

Springboot集成token认证

一、引出session问题以及token、鉴权

  1. session都是保存在内存中,认证用户增多,服务端开销明显增大。
  2. 若是认证的记录保存在某台服务器内存中时,意味着用户的下次请求只能够在该服务器内存中进行认证。
  3. CSRF跨站攻击

token的鉴权机制:http协议也是无状态的,不需要在服务端去保留用户的认证信息或者会话信息。这也就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录

鉴权流程:简单来说就是服务器根据前端传来的用户名与密码生成token并返回前端,前端之后的请求都会携带该cookie来进行执行操作认证。

  1. 用户使用用户名密码来请求服务器。
  2. 服务器进行验证用户的信息。
  3. 服务器通过验证生成token发送给用户一个token。
  4. 客户端存储token,并在每次请求时附送上这个token值。
  5. 服务端验证token值,并返回数据。

这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS

二、认识JWT(三部分详细构成)

JWT(JSON WEB TOKEN)是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串.

  • 第一部分:头部(header)。
  • 第二部分:载荷(payload),携带的信息。
  • 第三部分:签证(signature)。

三、Spring Security 

Spring Security

是一个强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的实际标准。Spring Security是一个可以为Java应用程序提供全面安全服务的框架。同时,它也可以轻松扩展以满足自定义需求。 

主要功能
Authentication (认证),就是用户登录
Authorization (授权):一旦身份验证成功,判断用户拥有什么权限,可以访问什么资源
防止跨站请求伪造(CSRF):Spring Security提供了内置的防护机制,可以防止跨站请求伪造攻击。
密码存储:Spring Security提供了多种密码存储格式,包括明文、加密和哈希。
集成其他安全框架:Spring Security可以与其他安全框架如OAuth2、JWT等进行集成,以提供更全面的安全解决方案。

SpringSecurity 采用的是责任链的设计模式,它有一条很长的过滤器链。

SecurityContextPersistenceFilter:每次请求处理之前将该请求相关的安全上下文信息加载到 SecurityContextHolder 中。
LogoutFilter:用于处理退出登录。
UsernamePasswordAuthenticationFilter:用于处理基于表单的登录请求,从表单中获取用户名和密码。
BasicAuthenticationFilter:检测和处理 http basic 认证。
ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException 。
FilterSecurityInterceptor:负责权限校验的过滤器,可以看做过滤器链的出口。

2. JWT校验登录的校验流程

首先前端一样是把登录信息发送给后端,后端查询数据库校验用户的账号和密码是否正确,正确的话则使用jwt生成token,并且返回给前端。以后前端每次请求时,都需要携带token,后端获取token后,使用jwt进行验证用户的token是否无效或过期,验证成功后才去做相应的逻辑。

四、Spring Boot整合Redis、SpringSecurity、JWT

 

  1. 添加依赖项在 pom.xml 文件中添加以下依赖项:
   <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency>
</dependencies>

 创建Redis配置类

@Configuration
public class RedisConfig {@Value("${spring.redis.host}")private String host;@Value("${spring.redis.port}")private int port;@Beanpublic JedisConnectionFactory jedisConnectionFactory() {return new JedisConnectionFactory(new RedisStandaloneConfiguration(host, port));}@Beanpublic RedisTemplate<String, Object> redisTemplate() {final RedisTemplate<String, Object> template = new RedisTemplate<>();template.setConnectionFactory(jedisConnectionFactory());return template;}
}

 创建 JwtTokenUtil 类,用于生成和验证JWT令牌。

@Component
public class JwtTokenUtil implements Serializable {private static final long serialVersionUID = -2550185165626007488L;private static final String secret = "mySecret";public String getUsernameFromToken(String token) {return getClaimFromToken(token, Claims::getSubject);}public Date getExpirationDateFromToken(String token) {return getClaimFromToken(token, Claims::getExpiration);}public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {final Claims claims = getAllClaimsFromToken(token);return claimsResolver.apply(claims);}private Claims getAllClaimsFromToken(String token) {return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();}private Boolean isTokenExpired(String token) {final Date expiration = getExpirationDateFromToken(token);return expiration.before(new Date());}public String generateToken(UserDetails userDetails) {Map<String, Object> claims = new HashMap<>();return doGenerateToken(claims, userDetails.getUsername());}private String doGenerateToken(Map<String, Object> claims, String subject) {return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + 5 * 60 * 60 * 1000)).signWith(SignatureAlgorithm.HS512, secret).compact();}public Boolean validateToken(String token, UserDetails userDetails) {final String username = getUsernameFromToken(token);return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));}
}

 创建 JwtAuthenticationEntryPoint 类,用于处理未经授权的请求。

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {private static final long serialVersionUID = -7858869558953243875L;@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response,AuthenticationException authException) throws IOException {response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");}
}

 创建 JwtRequestFilter 类,用于解析和验证JWT令牌。

@Component
public class JwtRequestFilter extends OncePerRequestFilter {@Autowiredprivate MyUserDetailsService myUserDetailsService;@Autowiredprivate JwtTokenUtil jwtTokenUtil;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException {final String requestTokenHeader = request.getHeader("Authorization");String username = null;String jwtToken = null;if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {jwtToken = requestTokenHeader.substring(7);try {username = jwtTokenUtil.getUsernameFromToken(jwtToken);} catch (IllegalArgumentException e) {System.out.println("Unable to get JWT Token");} catch (ExpiredJwtException e) {System.out.println("JWT Token has expired");}} else {logger.warn("JWT Token does not begin with Bearer String");}if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {UserDetails userDetails = this.myUserDetailsService.loadUserByUsername(username);if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);}}chain.doFilter(request, response);}
}

 配置Spring Security

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;@Autowiredprivate UserDetailsService jwtUserDetailsService;@Autowiredprivate JwtRequestFilter jwtRequestFilter;@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception {httpSecurity.csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll().anyRequest().authenticated().and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);}
}

http://www.lryc.cn/news/331242.html

相关文章:

  • 计算机网络_工具
  • 如何实现一个Java的@注解?
  • 嵌入式|蓝桥杯STM32G431(HAL库开发)——CT117E学习笔记12:DAC数模转换
  • 迅饶科技 X2Modbus 网关 GetUser 信息泄露漏洞复现
  • 修改亚马逊云科技账户的密码和MFA
  • 提升性能与精准追踪:SkyWalking自定义跟踪忽略插件
  • 第十三届蓝桥杯大赛软件赛省赛CC++大学B组
  • zookeeper监听集群节点的实现zkclient组件实现方案(Java版)
  • 【ArduinoQuartus】在小脚丫STEP CYC10上安装PulseRain Reindeer并在软核上运行基础功能
  • 【电路笔记】-逻辑与门
  • 蓝桥杯练习——拼出一个未来
  • stm32f103c8t6学习笔记(学习B站up江科大自化协)-SPI
  • 云计算的安全需求
  • 【C++】编程规范之表达式原则
  • Python人工智能基础知识:理解神经网络与机器学习的基本概念
  • 10_MVC
  • 【Java多线程(4)】案例:设计模式
  • 时序预测 | Matlab实现CPO-BiLSTM【24年新算法】冠豪猪优化双向长短期记忆神经网络时间序列预测
  • java面试题(4)|Spring和Spring Boot之间有什么关联和区别
  • Spring Boot中前端通过请求接口下载后端存放的Excel模板
  • 构建企业级微服务平台:实现可扩展性、弹性和高效性
  • 存内计算技术在边缘计算、物联网设备中的应用及前景
  • C#使用Selenium驱动Chrome浏览器
  • 【软件工程】详细设计(二)
  • 数据质量决定大模型能力,景联文科技提供高质量大模型数据
  • 大话设计模式之状态模式
  • 【机器学习】“强化机器学习模型:Bagging与Boosting详解“
  • 《QT实用小工具·九》设备按钮控件
  • 计算机服务器中了helper勒索病毒怎么办,helper勒索病毒解密流程步骤
  • qT 地图显示飞机轨迹