springsecurity+oauth2.0分布式认证授权案例 JWT令牌服务配置5

一 jwt的概念

1.1 jwt作用

JSON Web Token JWT )是一个开放的行业标准( RFC 7519 ),它定义了一种简介的、自包含的协议格式,用于 在通信双方传递json对象 传递的信息经过数字签名可以被验证和信任 JWT 可以使用 HMAC算法或使用RSA的公钥/私钥对来签名,防止被篡改。

1.2 jwt可以的解决问题

当资源服务和授权服务不在一起时资源服务使用 RemoteTokenServices 远程请求授权 服务验证token ,如果访问量较大将会影响系统的性能 。
解决上边问题:
令牌采 用JWT格式 即可解决上边的问题,用户认证通过会得到一个 JWT 令牌, JWT令牌中已经包括了用户相关的信 息 客户端只需要携带JWT访问资源服务 资源服务根据事先约定的算法自行完成令牌校验 无需次都请求认证服务完成授权

1.3 jwt的特点

1 jwt基于json,非常方便解析
2 )可以在令牌中自定义丰富的内容,易扩展。
3 通过非对称加密算法及数字签名技术 JWT防止篡改 ,安全性高。
4 )资源服 务使用JWT可不依赖认证服务即可完成授权
缺点:
1) JWT 令牌较长,占存储空间比较大。

1.4 JWT令牌结构

JWT 令牌由三部分组成,每部分中间使用点( . )分隔,比如: xxxxx.yyyyy.zzzzz

1.4.1 头部

头部包括令牌的类型(即 JWT )及使用的哈希算法(如 HMAC SHA256 RSA

 1.4.2 payload

第二部分是负载,内容也是 一个json对象,它是存放有效信息的地方 ,它可以存放 jwt 提供的现成字段,比 如:iss (签发者) ,exp (过期时间戳) , sub (面向的用户)等,也可自定义字段。

  1.4.3  signature

第三部分是签名,此部分用于防止 jwt 内容被篡改。
这个部分使用 base64url 将前两部分进行编码,编码后使用点( . )连接组成字符串,最后使用 header 中声明 签名算法进行签名。

二 jwt的配置

2.1 在认证uaa中配置jwt令牌

1.在spt-ds-uaa-server认证工程中,将前面章节使用的基于内存的令牌注释掉,使用jwt令牌

2.代码

package com.ljf.springsecurity.oauth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

/**
 * @ClassName: TokenConfig
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2021/08/29 12:49:39 
 * @Version: V1.0
 **/
@Configuration
public class TokenConfig {
    private 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();
    }
    **/
}

2.2 在认证服务配置类中使用jwt令牌

2.具体代码

package com.ljf.springsecurity.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;


import java.util.Arrays;

/**
 * @ClassName: AuthorizationServer
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2021/08/29 12:46:21 
 * @Version: V1.0
 **/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private AuthorizationCodeServices authorizationCodeServices;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtAccessTokenConverter accessTokenConverter;
    //step1:客户端详情服务
    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
     clients.inMemory()// 使用in-memory存储
                .withClient("c1")// client_id
                .secret(new BCryptPasswordEncoder().encode("secret"))//客户端密钥
                .resourceIds("res1")//资源列表
                .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
                .scopes("all")// 允许的授权范围
                .autoApprove(false)//false跳转到授权页面
                //加上验证回调地址
                .redirectUris("http://www.baidu.com");
    }
    //step2; 令牌管理服务
    @Bean
    public AuthorizationServerTokenServices tokenService() {
        DefaultTokenServices service=new DefaultTokenServices();
        service.setClientDetailsService(clientDetailsService);//客户端详情服务
        service.setSupportRefreshToken(true);//支持刷新令牌
        service.setTokenStore(tokenStore);//令牌存储策略
        //令牌增强
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
        service.setTokenEnhancer(tokenEnhancerChain);

        service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
        service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
        return service;
    }

    //step3: 设置授权码模式的授权码如何存取,暂时采用内存方式
   @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new InMemoryAuthorizationCodeServices();
    }
    //step4: 令牌服务端点
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                .authenticationManager(authenticationManager)//认证管理器
                .authorizationCodeServices(authorizationCodeServices)//授权码服务
                .tokenServices(tokenService())//令牌管理服务
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }
   //step5: 令牌安全约束
   @Override
   public void configure(AuthorizationServerSecurityConfigurer security){
       security
               .tokenKeyAccess("permitAll()")                    //oauth/token_key是公开
               .checkTokenAccess("permitAll()")                  //oauth/check_token公开
               .allowFormAuthenticationForClients()				//表单认证(申请令牌)
       ;
   }
}

2.3  生成jwt令牌

1.启动认证服务

2.使用密码模式生成jwt令牌:jwt令牌的字符串包含了用户信息和权限等信息

http://localhost:53020/uaa/oauth/token? client_id=c1&client_secret=secret&grant_type=password&username=shangsan&password=123

 2.4  验证jwt令牌信息

 2.5 在order资源服务中校验jwt令牌

在上一章节中,在资源服务拿到token令牌后,需要远程调用认证服务,解析token是否正确有效

那么现在使用jwt的token令牌,则不需要再调用认证服务了,直接解析jwt的token串进行校验

资源服务需要和授权服务拥有一致的签字、令牌服务等:
1、将授权服务中的TokenConfifig类拷贝到资源 服务中

2、屏蔽资源 服务原来的令牌服务类
3.代码实现类型tokenconfig:
package com.ljf.springsecurity.oauth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;

/**
 * @ClassName: TokenConfig
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2021/08/29 12:49:39 
 * @Version: V1.0
 **/
@Configuration
public class TokenConfig {
    private 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();
    }
    **/
}
4.资源配置类的操作:ResouceServerConfig
package com.ljf.springsecurity.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;

/**
 * @author Administrator
 * @version 1.0
 **/
@Configuration
@EnableResourceServer
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {
    @Autowired
    TokenStore tokenStore;

    public static final String RESOURCE_ID = "res1";//和认证服务器中的安全配置文件设置要一致
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID)//资源 id
                .tokenStore(tokenStore)
             //  .tokenServices(tokenService())//验证令牌的服务
                .stateless(true);
    }

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

        http
                .authorizeRequests()
                .antMatchers("/**").access("#oauth2.hasScope('all')")
                .and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    //资源服务令牌解析服务
    /**
  @Bean
    public ResourceServerTokenServices tokenService() {
        //使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
        RemoteTokenServices service=new RemoteTokenServices();
        service.setCheckTokenEndpointUrl("http://localhost:53020/uaa/oauth/check_token");
        service.setClientId("c1");
        service.setClientSecret("secret");
        return service;
    }
**/
}

 2.6 测试请求资源

1 )申请 jwt 令牌
2 )使用令牌请求资源
1.启动资源服务

2.访问资源
将前面得到的令牌  :
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX25hbWUiOiJiZWlqaW5nIiwic2NvcGUiOlsiYWxsIl0sImV4cCI6MTYzMDQyNDE1NCwiYXV0aG9yaXRpZXMiOlsicDEiLCJwMyJdLCJqdGkiOiJkMWQyN2NhMC1mMzMyLTQ4YzktYmY1NS1mM2NlNjFmMGY5MjYiLCJjbGllbnRfaWQiOiJjMSJ9.M-ZhEVNE6StpixS8r5LJylLrWUCgg7pCJwIkKIhPjMs
复制到Bearer 后面,进行请求

 2.7 将请求资源的角色改为其他

在controller中将请求资源的方法的角色改为其他,就是请求用户不具备的角色。

beijing 用户的角色为p1,p3,而现在访问此方法必须为p5角色才行。

 执行访问的结果:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,你想了解如何在Spring Boot中整合Spring Security和OAuth 2.0来实现token认证。下面是一个基本的步骤: 1. 添加依赖:在你的`pom.xml`文件中添加Spring Security和OAuth 2.0的依赖。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> ``` 2. 配置Spring Security:创建一个继承自`WebSecurityConfigurerAdapter`的配置类,并覆盖`configure`方法,配置Spring Security。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/oauth2/**", "/login/**", "/logout/**") .permitAll() .anyRequest() .authenticated() .and() .oauth2Login() .loginPage("/login") .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/") .deleteCookies("JSESSIONID"); } } ``` 这个配置类指定了哪些URL需要进行认证,`antMatchers`方法指定了不需要认证的URL。 3. 配置OAuth 2.0客户端:创建一个继承自`WebSecurityConfigurerAdapter`的配置类,并使用`@EnableOAuth2Client`注解开启OAuth 2.0客户端。 ```java @Configuration @EnableOAuth2Client public class OAuth2ClientConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { // 配置HTTP Security } @Bean public OAuth2AuthorizedClientService authorizedClientService( OAuth2ClientRegistrationRepository clientRegistrationRepository) { return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository); } } ``` 这个配置类可以用来配置OAuth 2.0的客户端,你可以在`configure`方法中添加一些额外的配置。 4. 配置OAuth 2.0客户端注册:在`application.properties`文件中配置OAuth 2.0的客户端注册信息。 ```properties spring.security.oauth2.client.registration.my-client-id.client-id=your-client-id spring.security.oauth2.client.registration.my-client-id.client-secret=your-client-secret spring.security.oauth2.client.registration.my-client-id.scope=your-scopes spring.security.oauth2.client.registration.my-client-id.authorization-grant-type=authorization_code spring.security.oauth2.client.registration.my-client-id.redirect-uri=your-redirect-uri ``` 这个配置文件中的`my-client-id`是你自己指定的客户端ID,你需要将其替换为你自己的信息。 这些步骤是实现Spring Boot中整合Spring Security和OAuth 2.0实现token认证的基本步骤。你可以根据自己的需求进行进一步的配置和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值