实时

您的位置:首页>资讯 >

Spring Boot的安全配置(三)

JWT

JWT(JSON Web Token)是一种用于在网络中传输安全信息的开放标准(RFC 7519)。它可以在各个服务之间安全地传递用户认证信息,因为它使用数字签名来验证信息的真实性和完整性。

JWT有三个部分,每个部分用点(.)分隔:


(资料图)

Header:通常包含JWT使用的签名算法和令牌类型。Payload:包含有关用户或其他主题的声明信息。声明是有关实体(通常是用户)和其他数据的JSON对象。声明被编码为JSON,然后使用Base64 URL编码。Signature:用于验证消息是否未被篡改并且来自预期的发送者。签名由使用Header中指定的算法和秘钥对Header和Payload进行加密产生。

在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构造函数中,以便在认证过程中使用。

下面是JwtAuthenticationFilterJwtAuthorizationFilter的实现:

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)是一种用于在网络中传输安全信息的开放标准(RFC7519)。它可以在各个服务之间安全地传递用户认证信息,因为它使用数字签

2023-04-07 01:23:20

01:39山东全力加快数字强省建设,算力应用的新模式、新业态加速涌现,为经济高质量发展提供重要支撑。奥德精密是一家从事气

2023-04-06 21:55:36

纽甜也叫尼尔甜,化学名称N-[N-(3,3一二甲基丁基)-L-α-天冬氨酰]-L-苯丙氨酸-1-甲酯,是一种功能性甜味剂,甜度达到我们熟知蔗糖的2000倍,产品

2023-04-06 20:49:17

有朋友咨询如何扫敬业福,今天就聊聊这个话题,希望可以帮到大家。首先打开手机,打开支付宝,在主页面上方有五福到活动,点击“点击进入”按

2023-04-06 19:32:16

广西2023年注册会计师全国统一考试报名时间及缴费时间地区报名时间缴费时间收费标准查看报名公告广西自治区4月6日至4月28日6月15日-6月30日广

2023-04-06 17:38:25

据市场监管总局消息,2022年,市场监管总局组织建筑材料产品质量国家监督抽查。本次抽查1704家企业生产的1920批次建筑材料产品,涉及热轧带肋

2023-04-06 16:49:11

1、中国人民解放军专业性、综合性的艺术团体。2、主要职能是:通过戏剧、音乐、舞蹈、曲艺、杂技等创作和演出,宣传爱国主

2023-04-06 15:58:29

重庆集中签约超2000亿元重大招商项目

2023-04-06 14:53:57

今天片仔癀股票行情观念:成绩平稳,走势较弱,短期需持币张望6月10日:短线大盘技能上还有回调压力耐今天可申购新股:无。

2023-04-06 13:56:30

河南省2023年上半年自考成绩什么时候公布考试成绩公布时间:2023年5月22日;成绩复核申请时间:2023年5月22日—5月28日,过期不再受理;5、毕业申请

2023-04-06 12:46:17

微软已将OpenAI的GPT-4集成到Microsoft365生产力应用套件中,这是一项非常艰巨的任务,但公司一直希望能够尽快完成。因此,微软动员了数百名员

2023-04-06 11:55:15

图为变体神人纹罐,马家窑文化马厂类型(约公元前2300年至公元前2000年),1975年于甘肃省兰州市土古台出土,甘肃省博物馆收藏。视觉中国供图

2023-04-06 11:05:25

消费需求是最终需求,消费也是畅通国内大循环的关键环节。今年《政府工作报告》提出,把恢复和扩大消费摆在优先位置。当前,为增强国内大循环

2023-04-06 10:07:51

股票估值低是什么意思?股票估值低通常就是指股票当前的价格低于内在价值的情况,一般是指股票价值被低估了。在股票投资中,往往股票估值月

2023-04-06 09:24:07

中国银河证券表示,目前美联储结束本轮加息周期时点临近,市场对降息预期升温,或将开启金价的新一轮上涨周期。上一轮黄金牛市(

2023-04-06 08:32:46

新湖南,主流新媒体,移动新门户。-分享自@新湖南

2023-04-06 07:11:01

1、《潍坊高等职业教育》杂志是由潍坊职业学院主办,反映我院乃至全市高等职业教育的教学、科研成果的综合性学术刊物。2、

2023-04-06 04:56:19

这里为大家带来steam2023春季促销结束时间一览的详细攻略,是很多玩家都遇到的一个难题,下面一起来看看具体的完成步骤。这款游戏中最近新出的

2023-04-05 23:45:48

这个品牌想要编写终极自动驾驶算法。本田已经为一种系统申请了专利,该系统将帮助未来的自动驾驶汽车更准确地预测其他道路使用者的行为。Ca

2023-04-05 19:37:56

张继科的瓜持续发酵,上面已经在调查,如果属实将会发公告,大家耐心等待,离真相不远了。那些索要资源的人也是看热闹不嫌事大,无论从道德还

2023-04-05 18:01:11