实时

您的位置:首页>资讯 >

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-08 06:13:18

4月7日,兴银兴慧一年持有混合A最新单位净值为1 0444元,累计净值为1 0444元,较前一交易日上涨0 14%。历史数据显示该基金近1个月上涨2 02%,

2023-04-08 02:40:07

4月6日,曾经的千亿房企新力控股公告称,其上市地位将被联交所取消。4月7日上午,就即将退市一事,新力控股相关人士直言“比较突然”,而就退

2023-04-07 22:17:21

智通财经APP讯城投控股600649600649SH披露2023年第一季度主要房产项目销售简报该公司璟雲里尚云里水尚华庭等三个项目一季度共计新增签约金额4570万元

2023-04-07 20:55:30

4月7日,太龙药业公布2022年年度报告,报告期内公司实现营业收入19 61亿元,同比增长20 2%;归属于上市公司股东的净利润为-7214 02万元,同比

2023-04-07 19:41:25

​虽是春日,赣南山区的清晨依旧凉气袭人。

2023-04-07 18:22:48

春节礼品规划ppt模板,春节期间走访礼品定制的很重要,不过要注意礼品的价格,要有新意,不能显得有新意,有创意新,不用太贵

2023-04-07 18:24:52

今日(4月7日),纸嫁衣官方公布纸嫁衣系列第五部解谜游戏《无间梦境》来生戏篇PV,新作《无间梦境》来生戏篇是纸嫁衣系列的第5个故事,这次的

2023-04-07 17:33:37

上海车展亮相北京奔驰EQESUV正式下线车质网日前获悉,北京奔驰EQESUV已于4月6日正式下线。新车定位为纯电中大型SUV,内外设计采用奔驰家族电动

2023-04-07 16:50:16

悬架系统的主要作用是减震、支撑和保持车身平衡,悬架当中的弹性单元,说人话就是弹簧,是悬挂系统中的主要支撑部分,它能够通过弹性变形来吸

2023-04-07 16:00:31

当然,在接下来的行程中周杰伦还会有收入的,内地已经官宣了好几个城市,这几场下来,周杰伦在内地赚的钱不能说能达到上亿,起码能够得上周杰

2023-04-07 14:53:29

内蒙古3月25日-3月31日煤炭平均价格为861 1元 吨环比下降0 7%据商务部重要生产资料市场监测系统数据显示:上周(3月25日-3月31日)全区重要生

2023-04-07 13:40:57

《泰晤士报》报道,埃里克森已经接近复出,而卢克-肖的伤势并不严重。卢克-肖在曼联1-0战胜布伦特福德的比赛第37分钟被换下,随后他走到球员通

2023-04-07 12:20:52

大家都知道六一是小孩的节日,随着时代的发展,每逢六一儿童节,很多年轻人也会掀起一股节日热潮不亚于520、双11,一些小伙伴会给老婆发微信红

2023-04-07 11:20:44

极目锐评|颖儿回应代言某家居品牌爆雷,“造谣式”爆料该整顿了!---4月6日,“狗仔”八卦媒体爆料称,艺人颖儿代言某家居品牌爆雷,该八卦媒

2023-04-07 10:38:48

股票代码:002672股票简称:东江环保东江环保股份有限公司投资者关系活动记录表编号:2023-01

2023-04-07 09:46:24

《黑帮的我成了高中生》改编自同名BL网路小说,描述梦想著上大学的黑社会男子,附身到了19岁的高中生身上后,用自己的本领惩罚加害者,并与饱

2023-04-07 09:05:16

周四(4月6日),美国三大股指全线收涨。截至收盘,道指涨0 01%,报33485 29点;标普500指数涨0 36%,报

2023-04-07 08:00:35

1、鱼。2、恐怖漫画伊藤润二创作。3、讲述了一个女主角在一个被感染并变成了全身臃肿、喷出恶臭可燃气体的怪物的世界里寻找自

2023-04-07 04:07:04

格隆汇4月6日丨和黄医药(HCM US)涨9%,报14 1美元,总市值24亿美元。和黄医药公布,公司已咨询中国国家药品监督管理局并达成一致,启动现正进行中的HM

2023-04-06 23:13:39