【Spring Security开发安全的REST服务】- 6.9 使用JWT替换默认令牌

6-9 使用JWT替换默认令牌

JWT(Json Web Token)三个特点

1、自包含:包含了一些跟项目相关的信息,可以被解析;
2、密签:可以用密钥来签名,签名指的是防止别人去篡改数据;
3、可扩展:自包含的信息可根据自己的需求扩展需要存放的信息;

6.9.1、配置TokenConfig类

在TokenConfig类中添加一个内部配置类JwtTokenConfig ;

package com.moss.securityapp;

import com.moss.securityapp.jwt.MossJwtTokenEnhancer;
import com.moss.securitycore.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

/**
 * Token保存配置
 *
 * @author lwj
 */
@Configuration
public class TokenStoreConfig {

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * redisTokenStore配置,下面注解中表示当在application.yml中配置了tokenStore属性的时候才启用
     * @return
     */
    @Bean
    @ConditionalOnProperty(prefix = "moss.security.oauth2", name = "tokenStore", havingValue = "redis")
    public TokenStore redisTokenStore() {
        return new RedisTokenStore(redisConnectionFactory);
    }

    /**
     * matchIfMissing :当tokenStore没有值的时候是否生效(不在application.yml文件中配置tokenStore这个属性的时候默认触发)
     * 当tokenStore = jwt的时候或则tokenStore没有配置的时候使用下面的配置
     */
    @Configuration
    @ConditionalOnProperty(prefix = "moss.security.oauth2", name = "tokenStore", havingValue = "jwt", matchIfMissing = true)
    public static class JwtTokenConfig {
        @Autowired
        private SecurityProperties securityProperties;

        @Bean
        public TokenStore JwtTokenStore() {
            return new JwtTokenStore(jwtAccessTokenConverter());
        }

        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter(){
            JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
            //  设置密签
            accessTokenConverter.setSigningKey(securityProperties.getOauth2().getJwtSigningKey());
            return accessTokenConverter;
        }

        @Bean
        @ConditionalOnMissingBean(name = "jwtTokenEnhancer")
        public TokenEnhancer jwtTokenEnhancer() {
            return new MossJwtTokenEnhancer();
        }

    }


}

在app项目中添加MossJwtTokenEnhancer

package com.moss.securityapp.jwt;

import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;

import java.util.HashMap;
import java.util.Map;

/**
 * jwt的token增强器
 * @author lwj
 */
public class MossJwtTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {
        Map<String, Object> info = new HashMap<>();
        info.put("company", "moss");
        // 设置附加信息
        ((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(info);
        return oAuth2AccessToken;
    }
}

在core项目的OAuth2Properties类中添加jwtToken的签名密钥;

private String jwtSigningKey = "moss";

6.9.2、修改认证服务器(MossAuthorizationServerConfig)

添加jwttoken的生成器,和增强器;

@Autowired(required = false)
private JwtAccessTokenConverter jwtAccessTokenConverter;

@Autowired(required = false)
private TokenEnhancer jwtTokenEnhancer;

修改该类中的configure方法

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
            .tokenStore(redisTokenStore)
            .authenticationManager(authenticationManager);
    //  如果在spring容器中能够找到jwt的token生成器的话则用jwt的
    if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> enhancers = new ArrayList<>();
        enhancers.add(jwtTokenEnhancer);
        enhancers.add(jwtAccessTokenConverter);
        enhancerChain.setTokenEnhancers(enhancers);
        // 一个处理链,先添加,再转换
        endpoints
                .tokenEnhancer(enhancerChain)
                .accessTokenConverter(jwtAccessTokenConverter);
    }
}

备注:application.yml文件中的配置说明;注释的“tokenStore”属性与TokenStoreConfig类中的注解相关,具体看该类中的注释;
在这里插入图片描述

6.9.3、测试JwtToken

获取jwttoken
在这里插入图片描述
返回结果
在这里插入图片描述
作为自包含的token的特性,我们可以将token值复制到jwt在线解析上去解析系统生成的token;
在这里插入图片描述
接下来我们通过拿到的jwtToken来试着请求下用户信息
在这里插入图片描述
在这里插入图片描述
我们发现返回的body中没有值,也就是说我们的UserController中的方法没有接收到值
在这里插入图片描述

6.9.4、解析使用jwtToken的请求方法

6.9.4.1、在demo项目的pom.xml文件中添加解析依赖
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
6.9.4.1、修改UserController中的me方法
/**
 * 获取用户信息
 *
 * @param user @AuthenticationPrincipal UserDetails 原来的接收参数,现在改成了Authentication,实际还需要解析处理
 * @return
 */
@GetMapping("/me")
public Object getCurrentUser(Authentication user, HttpServletRequest request) throws UnsupportedEncodingException {
    String header = request.getHeader("Authorization");
    String token = StringUtils.substringAfter(header, "bearer ");
    //  由于在写入的时候用的是另一个
    Claims claims = Jwts.parser().setSigningKey(securityProperties.getOauth2().getJwtSigningKey().getBytes("utf-8"))
            .parseClaimsJws(token).getBody();
    /** 解析token增强器中补充的字段company
     * {@link MossJwtTokenEnhancer#enhance(OAuth2AccessToken, OAuth2Authentication)} */

    String company = (String) claims.get("company");
    log.info("-->{}", company);
    return user;
}
6.9.2.4、重启服务测试

在这里插入图片描述
在这里插入图片描述
response中的body中的部分内容为全部的内容,具体需要可自行修改解析部分和增强器部分的代码;
至此,使用Jwt替换默认的token令牌的配置就完结了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值