JWT(JSON Web Token)是一种用于在网络中传输安全信息的开放标准(RFC 7519)。它可以在各个服务之间安全地传递用户认证信息,因为它使用数字签名来验证信息的真实性和完整性。
JWT有三个部分,每个部分用点(.)分隔:
(资料图)
在Spring Boot中,您可以使用Spring Security和jjwt库来实现JWT的认证和授权。下面是一个使用JWT的示例:
@Configuration@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Value("${jwt.secret}") private String jwtSecret; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers(HttpMethod.POST, "/api/authenticate").permitAll() .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtSecret)) .addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtSecret)) .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(new JwtAuthenticationProvider(jwtSecret)); }}
在上面的示例中,SecurityConfig
类继承了WebSecurityConfigurerAdapter
并使用了@EnableWebSecurity
注解启用Spring Security。configure()
方法使用HttpSecurity
对象来配置HTTP请求的安全性。.csrf().disable()
禁用了CSRF保护。.authorizeRequests()
表示进行授权请求。.antMatchers(HttpMethod.POST, "/api/authenticate").permitAll()
表示允许POST请求到/api/authenticate
路径。.anyRequest().authenticated()
表示要求所有其他请求都需要身份验证。.addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtSecret))
和.addFilter(new JwtAuthorizationFilter(authenticationManager(), jwtSecret))
分别添加JWT认证和授权过滤器。.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
指定了会话管理策略。
configure()
方法中还有一个configure(AuthenticationManagerBuilder auth)
方法,它使用JwtAuthenticationProvider
类配置身份验证。在这里,jwtSecret
被注入到JwtAuthenticationProvider
构造函数中,以便在认证过程中使用。
下面是JwtAuthenticationFilter
和JwtAuthorizationFilter
的实现:
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; private final String jwtSecret; public JwtAuthenticationFilter(AuthenticationManager authenticationManager, String jwtSecret) { this.authenticationManager = authenticationManager; this.jwtSecret = jwtSecret; setFilterProcessesUrl("/api/authenticate"); } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) { try { LoginRequest loginRequest = new ObjectMapper().readValue(request.getInputStream(), LoginRequest.class); Authentication authentication = new UsernamePasswordAuthenticationToken( loginRequest.getUsername(), loginRequest.getPassword() ); return authenticationManager.authenticate(authentication); } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) { UserPrincipal userPrincipal = (UserPrincipal) authResult.getPrincipal(); String token = Jwts.builder() .setSubject(userPrincipal.getUsername()) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + 864000000)) .signWith(SignatureAlgorithm.HS512, jwtSecret) .compact(); response.addHeader("Authorization", "Bearer " + token); }}
JwtAuthenticationFilter
类继承了UsernamePasswordAuthenticationFilter
类,它用于处理基于用户名和密码的身份验证。它还使用AuthenticationManager
来验证用户名和密码是否正确。jwtSecret
在构造函数中被注入,用于生成JWT令牌。
在attemptAuthentication()
方法中,LoginRequest
对象被反序列化为从请求中获取的用户名和密码。这些值被封装到UsernamePasswordAuthenticationToken
中,并传递给AuthenticationManager
以验证用户身份。
在身份验证成功后,successfulAuthentication()
方法被调用。在这里,UserPrincipal
对象被从Authentication
对象中获取,然后使用Jwts
类生成JWT令牌。setSubject()
方法将用户名设置为JWT主题。setIssuedAt()
方法设置JWT令牌的发行时间。setExpiration()
方法设置JWT令牌的到期时间。signWith()
方法使用HS512算法和jwtSecret
密钥对JWT令牌进行签名。最后,JWT令牌被添加到响应标头中。
下面是JwtAuthorizationFilter
的实现:
public class JwtAuthorizationFilter extends BasicAuthenticationFilter { private final String jwtSecret; public JwtAuthorizationFilter(AuthenticationManager authenticationManager, String jwtSecret) { super(authenticationManager); this.jwtSecret = jwtSecret; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String authorizationHeader = request.getHeader("Authorization"); if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) { chain.doFilter(request, response); return; } String token = authorizationHeader.replace("Bearer ", ""); try { Jws claimsJws = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token); String username = claimsJws.getBody().getSubject(); List authorities = (List) claimsJws.getBody().get("authorities"); List grantedAuthorities = authorities.stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, grantedAuthorities); SecurityContextHolder.getContext().setAuthentication(authentication); chain.doFilter(request, response); } catch (JwtException e) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); } }}
JwtAuthorizationFilter
类继承了BasicAuthenticationFilter
类,并覆盖了doFilterInternal()
方法。在这个方法中,请求头中的Authorization
标头被解析,如果它不是以Bearer
开头,则直接传递给过滤器链。否则,从令牌中解析出主题(用户名)和授权信息,然后创建一个包含用户身份验证和授权信息的Authentication
对象,并将其设置到SecurityContextHolder
中。
如果JWT令牌无效,JwtException
将被抛出,并返回HTTP 401未经授权的错误。
JWT(JSONWebToken)是一种用于在网络中传输安全信息的开放标准(RF...
南方财经4月7日电,近日,杭州阿里巴巴网络科技有限公司发生工商变...
近日,科德宝高性能材料服饰(科德宝)推出了100%回收热塑性弹性体(rT...
帮我搜一下最近最红的教师节礼物,我已经准备好了,今年的教师节马...
当地时间4月6日晚,美国孟菲斯动物园发布消息称,动物园将于4月8日...
乐居楼盘测评系列测评师:乐居买房乐居楼盘测评系列是来自专业测评...
1、云教学平台打开平台,输入用户名和密码即可登录2、云教学平台课...
1、哪个农商银行。2、浙江农信是96596查询号台就可找到。本文就为大...
1、不知道,应该是,据说是在暗黑门里的。2、没人证实,只能提供这...
1、大航海时代4威力加强版是日本Koei公司1999年推出的经典单机游戏...
本周从4月3日到4月9日,金牛座、摩羯座、处女座会更加脚踏实地,很...
1、乔迁时有暖房、温锅之说。2、新房子往往没有人住过,所以没有“...
4月6日消息,《最终幻想:像素重置版》将于北京时间4月19日晚上11点...
据西班牙加泰罗尼亚RAC1报道,加泰罗尼亚联队已经确定了赛季末传统...
1、山羊奶酪菠菜玛芬是以中筋粉、泡打粉为主料的菜品。本文到此分享...
观点网讯。4月6日,华福-武汉临空港投资集团系列及1号资产支持专项...
随着夏天的临近,降水增多、用电上升,农村社区防涝排水和安全用电...
3月31日,由北京市经济和信息化局、北京市海淀区人民政府、北京市延...
今天(6日),自然资源部印发加强国土空间生态修复项目规范实施和监...
小郭说,4月3日下午,当他从缅甸方面的警察局里出来上车时,还以为...
男子深夜到派出所咨询自己是不是逃犯民警:你是
今日NBA常规赛,湖人客场118-125不敌快船。今日湖人球星安东尼-戴维...
1、clbt是科瑞文件,可以使用科瑞计算簿软件或cad来打开。2、科瑞计...
前、现任领导人双英出访引发各界热议。民众党台北市议员林珍羽5日...
4月4日,英杰电气(300820)融资买入1614 24万元,融资偿还724 83...
绿萝为多年生常绿藤本植物。春、夏、秋三季可放在东面或北面窗台附...
1、使用场合用于森林采伐、造材、打枝等以及贮木场造材、铁路枕木锯...
朱奕奕表示,民法典以及担保法司法解释出台以后,法院认定上市公司...
欢迎观看本篇文章,小勉来为大家解答以上问题。s24王者赛季结束时间...
本泽马在社媒晒出了自己身着神秘黑色套装的图片,并配文道:“给我...