0


【Spring Security系列】Spring Security整合JWT:构建安全的Web应用

前言

在企业级开发或者我们自己的课程设计中,确保用户数据的安全性和访问控制非常重要。而Spring Security和JWT是都两个强大的工具,它俩结合可以帮助我们实现这一目标。

Spring Security提供了全面的安全功能,而JWT则是一种用于身份验证的令牌机制。
在这里插入图片描述

JWT简单介绍

前面两个章节介绍过了Spring Security,这里就不再赘述了!!!

JWT是一种轻量级的身份验证和授权机制,通过发送包含用户信息的加密令牌来实现身份验证。这个工具我们在前面的文章中也提起过。

整合步骤与代码实现

目前大部分项目,大多数是使用前后端分离的模式。前后端分离的情况下,我们使用SpringSecurity解决权限问题的最常见的方案就是SpringSecurity+JWT 。

在这里插入图片描述

添加依赖
首先,我们需要在项目的pom.xml文件中添加Spring Security和JWT的依赖:

<!--JWT--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.8.1</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><!--工具包--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.0.M3</version></dependency><dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.75</version></dependency>

接下来配置Spring Security,在Spring Security配置类中,我们自定义用户详情服务和认证管理器,并配置HTTP安全策略:

@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@AutowiredprivateJwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;@AutowiredprivateJwtRequestFilter jwtRequestFilter;@AutowiredpublicvoidconfigureGlobal(AuthenticationManagerBuilder auth)throwsException{  
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());}@Bean@OverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}@BeanpublicPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}@Overrideprotectedvoidconfigure(HttpSecurity http)throwsException{  
        http  
            .csrf().disable().authorizeRequests().antMatchers("/authenticate").permitAll().anyRequest().authenticated().and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);  
  
        http.addFilterBefore(jwtRequestFilter,UsernamePasswordAuthenticationFilter.class);}}

实现JWT生成和验证,我们创建一个JWT工具类,用于生成和解析JWT:

java
@ComponentpublicclassJwtTokenUtil{privateString secret ="your_secret_key";// 私钥,用于签名JWT  publicStringgenerateToken(UserDetails userDetails){Map<String,Object> claims =newHashMap<>();returnJwts.builder().setClaims(claims).setSubject(((User) userDetails).getUsername()).setIssuedAt(newDate(System.currentTimeMillis())).setExpiration(newDate(System.currentTimeMillis()+1000*60*60*10))// 10小时过期  .signWith(SignatureAlgorithm.HS512, secret).compact();}publicStringgetUsernameFromToken(String token){returngetClaimFromToken(token,Claims::getSubject);}publicDategetExpirationDateFromToken(String token){returngetClaimFromToken(token,Claims::getExpiration);}private<T>TgetClaimFromToken(String token,Function<Claims,T> claimsResolver){finalClaims claims =getAllClaimsFromToken(token);return claimsResolver.apply(claims);}privateClaimsgetAllClaimsFromToken(String token){returnJwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();}publicbooleanvalidateToken(String token,UserDetails userDetails){finalString username =getUsernameFromToken(token);return(username.equals(userDetails.getUsername())&&!isTokenExpired(token));}privatebooleanisTokenExpired(String token){finalDate expiration =getExpirationDateFromToken(token);return expiration.before(newDate());

在这里插入图片描述

创建JWT过滤器与认证管理器

为了在用户每次请求时验证JWT,我们需要创建一个自定义的过滤器。同时,我们还需要一个认证管理器来处理用户的登录请求。

我们实现JWT过滤器

@ComponentpublicclassJwtRequestFilterextendsOncePerRequestFilter{@AutowiredprivateJwtTokenUtil jwtTokenUtil;@AutowiredprivateUserDetailsService userDetailsService;@OverrideprotectedvoiddoFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain)throwsServletException,IOException{finalString 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(Exception e){  
                logger.error("Unable to get JWT Token");}}if(username !=null&&SecurityContextHolder.getContext().getAuthentication()==null){UserDetails userDetails =this.userDetailsService.loadUserByUsername(username);if(jwtTokenUtil.validateToken(jwtToken, userDetails)){UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =newUsernamePasswordAuthenticationToken(userDetails,null, userDetails.getAuthorities());  
                usernamePasswordAuthenticationToken.setDetails(newWebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);}}  
  
        filterChain.doFilter(request, response);}}

认证管理器,我们创建一个AuthenticationManager的实现来处理用户的登录请求:

@ServicepublicclassCustomAuthenticationManagerimplementsAuthenticationManager{@AutowiredprivateUserDetailsService userDetailsService;@AutowiredprivatePasswordEncoder passwordEncoder;@OverridepublicAuthenticationauthenticate(Authentication authentication)throwsAuthenticationException{String username = authentication.getName();String password = authentication.getCredentials().toString();UserDetails userDetails = userDetailsService.loadUserByUsername(username);if(userDetails ==null){thrownewBadCredentialsException("User not found");}if(!passwordEncoder.matches(password, userDetails.getPassword())){thrownewBadCredentialsException("Wrong password");}returnnewUsernamePasswordAuthenticationToken(userDetails,null, userDetails.getAuthorities());}}

创建控制层LoginController

RestController@RequestMapping("/security")publicclassAuthenticationController{@AutowiredprivateCustomAuthenticationManager authenticationManager;@AutowiredprivateJwtTokenUtil jwtTokenUtil;@AutowiredprivateUserDetailsService userDetailsService;@PostMapping("/login")publicResponseEntity<?>createAuthenticationToken(@Valid@RequestBodyLoginRequest loginRequest)throwsException{authenticate(loginRequest.getUsername(), loginRequest.getPassword());finalUserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());finalString token = jwtTokenUtil.generateToken(userDetails);returnResponseEntity.ok(newJwtAuthenticationResponse(token));}privatevoidauthenticate(String username,String password)throwsException{try{  
            authenticationManager.authenticate(newUsernamePasswordAuthenticationToken(username, password));}catch(DisabledException e){thrownewException("USER_DISABLED", e);}catch(BadCredentialsException e){thrownewException("INVALID_CREDENTIALS", e);}}}

使用ApiFox测试

在这里插入图片描述
这样,我们就可以构建一个安全且高效的Web应用了。

小结

Spring Security提供了强大的身份验证和授权功能,而JWT则提供了一种轻量级的令牌机制来验证用户身份。通过结合使用,我们可以实现无缝的用户身份验证和访问控制,然后保护我们应用的数据安全。

文章到这里就先结束了,后续会继续分享相关的知识点。
在这里插入图片描述


本文转载自: https://blog.csdn.net/qq_53847859/article/details/137940106
版权归原作者 小威要向诸佬学习呀 所有, 如有侵权,请联系我们删除。

“【Spring Security系列】Spring Security整合JWT:构建安全的Web应用”的评论:

还没有评论