首页 > 其他分享 >OAuth2.0实战使用JWT令牌认证

OAuth2.0实战使用JWT令牌认证

时间:2024-01-23 16:06:55浏览次数:33  
标签:令牌 return service JWT new OAuth2.0 public

JWT分为三部分:头部、载荷、签名。如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJhZG1pbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE3MDU5OTQ0MzgsImF1dGhvcml0aWVzIjpbIlJPTEVfYWRtaW4iXSwianRpIjoiM2RiYjVkNGUtN2Q3My00ODI3LTlkOGYtMmI3OGVmMmVmZTExIiwiY2xpZW50X2lkIjoiYzEifQ.
eAVj9_lLpUC99jJbLwV2OwNrPvjGqoKgtHm5_jlgqBg

头部定义了JWT基本信息,如类型和签名

载荷包含了一些基本信息(签发时间、过期时间),另外还可以添加一些自定义的信息,比如用户的部分信息。

签名部分将前两个字符串用.连接后,使用头部定义的加密算法,利用密钥进行签名,并将签名信息附在最后。

OAuth2.0分为认证授权中心、资源服务,认证中心用于颁发令牌,资源服务解析令牌并且提供资源。

令牌配置

@Configuration
public class TokenConfig {

    /**
     * 对称密钥,资源服务器使用该密钥来验证
     */
    private final static String SIGNING_KEY = "uaa123";

    @Bean
    public TokenStore tokenStore(){
        //JWT令牌存储方案
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(SIGNING_KEY);
        return converter;
    }

   /* @Bean
	 public TokenStore tokenStore() {
		 //使用内存存储令牌(普通令牌)
		 return new InMemoryTokenStore();
	 }*/

}

1、JwtAccessTokenConverter

令牌增强类,用于JWT令牌和OAuth身份进行转换

2、TokenStore

令牌的存储策略,这里使用的是JwtTokenStore,使用JWT的令牌生成方式,其实还有以下两个比较常用的方式

RedisTokenStore:将令牌存储到Redis中,此种方式相对于内存方式来说性能更好。

JdbcTokenStore:将令牌存储到数据库中,需要新建对应的表。

3、SIGNING_KEY

JWT签名的密钥,这里使用的是对称加密,资源服务也要使用相同的密钥进行校验和解析JWT令牌。

认证授权中心

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private JwtAccessTokenConverter accessTokenConverter;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private AuthenticationManager authenticationManager;

    //客户端详情服务,也就是configure(ClientDetailsServiceConfigurer clients)方法
    @Autowired
    private ClientDetailsService clientDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //这里是第三方合作用户的客户id,密钥的配置
        //使用in-memory存储
        clients.inMemory()
                // 设置我们接受的客户端的编号
                .withClient("c1")
                // secret密码
                .secret(passwordEncoder().encode("123456"))
                // 认证模式:password模式
                .authorizedGrantTypes("password", "refresh_token")
                // token的过期时间
                .accessTokenValiditySeconds(1800)
                // 资源id
                .resourceIds("res1")
                //作用域  读写 针对资源的操作权限
                .scopes("all");
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 令牌管理服务
     */
    @Bean
    public AuthorizationServerTokenServices tokenService() {

        DefaultTokenServices service = new DefaultTokenServices();
        service.setClientDetailsService(clientDetailsService);
        service.setSupportRefreshToken(true);// 支持刷新
        service.setTokenStore(tokenStore);// 令牌存储
        //设置令牌增强,使用JwtAccessTokenConverter进行转换
        service.setTokenEnhancer(accessTokenConverter);
        // 令牌默认有效期2小时
        service.setAccessTokenValiditySeconds(7200); 
        // 刷新令牌默认有效期3天
        service.setRefreshTokenValiditySeconds(259200); 
        return service;
    }
    
    /**
    * 配置令牌访问的端点
    */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints
                // 指定认证管理器
                .authenticationManager(authenticationManager)
                // 授权码模式需要
                .authorizationCodeServices(authorizationCodeServices())
                // 令牌管理服务
                .tokenServices(tokenService())
                // jwt格式Token
                .accessTokenConverter(accessTokenConverter)
                // 允许post提交
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }

    /**
     * 授权码服务器
     */
    @Bean   
    public AuthorizationCodeServices authorizationCodeServices() {
        // 授权码模式的授权码采用内存方式存储
        return new InMemoryAuthorizationCodeServices();
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                // 提供公有密匙的端点,如果你使用JWT令牌的话, 允许
                .tokenKeyAccess("permitAll()")
                // oauth/check_token:用于资源服务访问的令牌解析端点,允许
                .checkTokenAccess("permitAll()")
                // 表单认证,申请令牌
                .allowFormAuthenticationForClients();
    }

令牌管理服务,使用的是DefaultTokenService这个实现类,其中可以配置令牌相关的内容,如access_token、refresh_token的过期时间,默认时间分别为12小时、30天。

设置令牌增强,使用JWT方式生成令牌,如下:

service.setTokenEnhancer(accessTokenConverter);

web安全配置

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    public void configure(AuthenticationManagerBuilder builder) throws Exception {
        builder.userDetailsService(myUserDetailsService());
    }

    @Bean
    public UserDetailsService myUserDetailsService() {
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
        userDetailsService.createUser(User.withUsername("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("admin").build());
        return userDetailsService;
    }
}

UserDetailsServices使用内存方式保存,创建一个用户。


OAuth2.0资源服务

@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    // 令牌存储策略
    private TokenStore tokenStore;

    // 授权服务的资源列表
    public static final String RESOURCE_ID = "res1";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources
                // 资源 id
                .resourceId(RESOURCE_ID)
//                // 令牌服务
//                .tokenServices(tokenService())
                // 令牌服务
                .tokenStore(tokenStore)
                .stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests().antMatchers("/**")
                // 所有的访问,授权访问都要是all,和认证服务器的授权范围一一对应
                .access("#oauth2.hasScope('all')")
                //去掉防跨域攻击
                .and().csrf().disable()
                //session管理
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

资源id和令牌服务配置到ResourceServerSecurityConfiguer中。

由于使用了JWT这种透明令牌,令牌本身携带着部分用户信息,不需要远程调用认证中心的接口校验令牌。

测试

1、使用密码模式获取令牌

OAuth2.0实战使用JWT令牌认证_OAuth2.0

可以看到已经成功返回了JWT令牌。

2、携带令牌调用资源服务

OAuth2.0实战使用JWT令牌认证_jwt_02


标签:令牌,return,service,JWT,new,OAuth2.0,public
From: https://blog.51cto.com/u_11315052/9380593

相关文章

  • python+flask_restful使用jwt
    正在做毕设,由于毕设需求使用python+flask,使用jwt目的是对请求进行保护,我的项目采用vue3+flask前后端分离实现,进入正题:使用jwt,首先下载扩展pipinstallFlask-JWT-Extended然后在项目中注册使用,我的项目结构是这样的 在exts.py中引入jwt扩展,fromflask_jwt_extendedimpo......
  • 下一代云原生网关Higress:基于Wasm开发JWT认证插件
    什么是HigressHigress是基于阿里内部的EnvoyGateway实践沉淀、以开源Istio+Envoy为核心构建的下一代云原生网关,实现了流量网关+微服务网关+安全网关三合一的高集成能力,深度集成Dubbo、Nacos、Sentinel等微服务技术栈,能够帮助用户极大的降低网关的部署及运维成本且能力不打......
  • SpringBoot使用jwt实现接口带令牌访问
    1、 添加依赖<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>${jwt.version}</version></dependency>2、先定义一个用户实体@Data@TableName("t_user")publicclass......
  • 认证授权JWT
    JWT1、从JWT的全称可以看出,JWT本身也是Token,一种规范化之后的JSON结构的Token。JWT自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储Session信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力(因为session还需要保存,但是jwt只要签名验证......
  • 手拉手后端Springboot整合JWT
    环境介绍技术栈springboot+mybatis-plus+mysql+java-jwt软件版本mysql8IDEAIntelliJIDEA2022.2.1JDK1.8SpringBoot2.7.13mybatis-plus3.5.3.2JsonWeb令牌简称JWTToken是在服务端产生的一串字符串是客户端访问资源接口(AP)时所需要的资源凭证。Token认证Token是在服务端产生的一......
  • 手拉手Springboot整合JWT
    环境介绍技术栈springboot+mybatis-plus+mysql+java-jwt软件版本mysql8IDEAIntelliJIDEA2022.2.1JDK1.8SpringBoot2.7.13mybatis-plus3.5.3.2JsonWeb令牌简称JWTToken是在服务端产生的一串字符串是客户端访问资源接口(AP)时所需要的资源凭证。 Token认证流程1、客户端使用用......
  • 浅学JWT跨域认证
    JsonWeb令牌简称JWT由Header+Payload+Signature组成HeaderJWT头是一个描述JWT元数据的JSON对象,alg属性表示签名使用的算法,默认为HMACSHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64URL算法将上述JSON对象转换为字符串保存Payload有效载荷部分,是JWT的......
  • 【Azure APIM】在APIM中实现JWT验证不通过时跳转到Azure登录页面
    问题描述在APIM中配置JWT策略,验证JWT,如果认证失败,则跳转到AzureEntraID的Login页面。 问题解答要实现JWT验证失败后,跳转到AzureEntraID的Login页面。需要使用到两种策略:validate-jwt:https://learn.microsoft.com/en-us/azure/api-management/validate-jwt-policyretu......
  • 什么是JWT令牌
    当下,JWT(JSONWebToken)令牌认证已经变得越来越流行。本文主要介绍JWT令牌认证与传统的Session会话认证机制的区别。为什么需要认证?HTTP是一种无状态协议,那就意味着当前的客户端的请求与任何之前的请求是独立不依赖的,而服务器也并不会记录任何请求信息。例如,如果你只是简单地访问......
  • 前端学习笔记202310学习笔记第一百贰拾叁天-nodejs-登录鉴权-JWT鉴权之14
    ......