首页 > 行业 >

天天通讯!Spring Boot的安全配置(三)

2023-04-07 14:29:29 来源:腾讯云

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未经授权的错误。

上一篇:

【全球热闻】江南春笋加速北上 物流配送提速加快优质农产品流通

下一篇:

最后一页

x
推荐阅读

天天通讯!Spring Boot的安全配置(三)

【全球热闻】江南春笋加速北上 物流配送提速加快优质农产品流通

【新要闻】社交平台轻盐App:因业务调整,服务器将永久关闭

定价申报什么意思?申报税额是什么? 环球快播

“江盾号”渔政执法船首航 长江无锡(江阴)段禁渔禁捕添利器

【全球播资讯】环西自行车中国挑战赛6月进京

【时快讯】百万开户后,银行直面个人养老金留客难题

科学家发现未知铀同位素 世界热议

外卖平台九成订单来自广东

4月6日基金净值:万家新机遇龙头企业混合A最新净值1.9201,跌0.52%

今日最新!高粱米水饭的做法(高粱米水饭怎么做好吃)

全球实时:濮存昕执导 北京人艺新排契诃夫名作《海鸥》

世界热议:韩国电池材料制造商Ecopro或将斥资2万亿韩元扩产

世界快播:中骏集团控股(01966.HK)3月实现合同销售金额约46.08亿元

重庆姐弟坠亡案二审仍在进行中,有市民在高院门口“蹲”判决 全球热讯

ONEXPLAYER 2:全新掌上游戏机采用英特尔酷睿 i7-1370P 处理器|全球热资讯

广西蚕业技术推广站特派员赴蒙山县开展技术指导服务

中国汽车行业数字化转型解决方案白皮书

詹姆斯:昨天打完加时很晚才回来 这是日程安排冲突的比赛之一|全球今日报

泓博医药董秘回复:跟chatGPT之类的自然语言处理工具不同,药物设计具有很强的专业性和专属性

云南德宏发现中国龙脑香科植物新记录——盈江柳安

城门失火殃及池鱼_城门失火 世界微头条

每日头条!罗伊斯:上半时莱比锡就把我们吞没了,这样的表现显然不够好

清明祭英烈 传承爱国志

高光谱观测卫星在轨投用-世界快资讯

焦点热门:nia是什么意思(nia意思是:无意义;在方言中是“没有”的意思)

元宵节送什么给男生

彻底崩了!AI遭全球“围剿”,A股咋应对?超9000人联名“封杀”,巴菲特又要“抄底”?

每日快播:排骨肉怎么做好吃_排骨肉的烹饪方法

【独家焦点】创元科技:参股公司创元期货申请IPO

【报资讯】甜字怎么组词_甜组词有哪些

yy频道管理权限(yy频道管理)|每日资讯

清明食馓子 非遗手艺里的老味道

北京硕博毕业生人数首超本科,专家:切忌盲目追求高学历-全球报资讯

今日热讯:海南全岛封关意义重大

再见内马尔!巴黎亏本清洗,姆总对他零容忍,可去英超豪门冲金球

全球速读:视频|特朗普被传讯后首次讲话:从未想到这种事发生在美国

提离职后,领导按排部门聚餐,是挽留还是送行

国务院任免国家工作人员

三星折叠新机Galaxy Z Fold 5细节曝光:将采用水滴状铰链

深爱过张继科的两任女友,一个愿意改造他,一个无法容忍他 当前播报

王思聪带两美女一起吃饭,新女友神似小肉安,看上去只有20岁左右 天天通讯

江苏靖江:鲜花祭扫生态安葬蔚然成风 焦点关注

环球最资讯丨焦作公安网官网_焦作市公安局网站

塞内加尔举行阅兵式庆祝独立63周年

工作后才懂,大学生“校招”和“社招”的区别,幸好听了学姐的话

前沿资讯!深圳国土局评估价查询系统-深圳国土局评估价查询

【财经】报告:北京房地产市场迎来良好开局-天天微资讯

【全球独家】镇平:中俄贸易港项目达成合作框架

郑州启动数据要素市场化配置改革 欲建“中国数仓” 即时