栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring security oauth2.x迁移到spring security5.x - 资源服务器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring security oauth2.x迁移到spring security5.x - 资源服务器

spring cloud升级到2020.x以后不再包含spring security
项目可以继续使用spring security oauth 2.x版本或者升级到spring security 5.x
官方迁移指引

差异
  1. 废弃@EnableResourceServer注解,改为使用oauth2ResourceServer方法
  2. 废弃ResourceServerConfigurerAdapter,改为在WebSecurityConfigurerAdapter暴露相同功能
  3. 鉴权表达式变更
spring security oauth 2.xspring security 5.x
access("#oauth2.hasScope(‘scope’)")hasAuthority(“SCOPE_scope”)
依赖

    org.springframework.boot
    spring-boot-starter-oauth2-resource-server


    com.nimbusds
    oauth2-oidc-sdk

注:使用 Opaque Token - 不透明令牌 模式,没有引入nimbusds依赖会报错java.lang.ClassNotFoundException: com.nimbusds.oauth2.sdk.http.HTTPResponse

配置

这里的参数继续读取2.x版本的配置文件的配置

public class ResourceServerConfig extends WebSecurityConfigurerAdapter {
    final String clientId;
    final String clientSecret;
    final String introspectionUrl;

    public ResourceServerConfig(
            @Value("${security.oauth2.client.client-id}") final String clientId,
            @Value("${security.oauth2.client.client-secret}") final String clientSecret,
            @Value("${security.oauth2.resource.tokenInfoUri}") final String introspectionUrl
    ) {
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.introspectionUrl = introspectionUrl;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests(
                authorizeRequestsCustomizer ->
                        authorizeRequestsCustomizer
                                .antMatchers("/api/**").hasAnyAuthority("SCOPE_scope")
                                .anyRequest().permitAll()
        ).oauth2ResourceServer(
                httpSecurityOAuth2ResourceServerConfigurer ->
                        httpSecurityOAuth2ResourceServerConfigurer
                                .opaqueToken()
                                .introspectionUri(introspectionUrl)
                                .introspectionClientCredentials(clientId, clientSecret)

        );
    }
}
老授权服务器兼容性改造

这样配置后访问如果仍使用2.x搭建的授权服务器资源会报错403 ,

Bearer error=“insufficient_scope”,error_description=“The request requires higher privileges than provided by the access token.”,error_uri=“https://tools.ietf.org/html/rfc6750#section-3.1”

原因是2.x中scope的格式是数组,而nimbusds需要逗号分隔的字符串,从而导致check_token的响应中scope无法正常反序列化。

不想升级spring security的话解决办法是自定义AccessTokenConverter将scope拼接为逗号分隔的字符串

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
	...
	endpoints.accessTokenConverter(new DefaultAccessTokenConverter() {
	    @Override
	    public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
	        Map response = super.convertAccessToken(token, authentication);
	        if (token.getScope() != null) {
	            response.put(
	                    AccessTokenConverter.SCOPE,
	                    StringUtils.join(token.getScope(), ',')
	            );
	        }
	        return response;
	    }
	});
	...
}
源码分析
  • 授权服务器令牌校验端点
    org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint
private AccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
@RequestMapping(value = "/oauth/check_token")
@ResponseBody
public Map checkToken(@RequestParam("token") String value) {
	...
	Map response = (Map)accessTokenConverter.convertAccessToken(token, authentication);
	...
	return response;
}
  • 授权服务器默认令牌转换器
    org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter
public Map convertAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
	// 此处scope属性是集合,序列化为json数组格式
	if (token.getScope()!=null) {
		response.put(scopeAttribute, token.getScope());
	}
}
  • 资源服务器令牌校验
    com.nimbusds.oauth2.sdk.TokenIntrospectionSuccessResponse
public Scope getScope() {
    try {
    	// 此处以字符串类型解析scope字段,实际上获得的是JSONArray对象
        return Scope.parse(JSONObjectUtils.getString(this.params, "scope"));
    } catch (ParseException var2) {
        return null;
    }
}
  • 资源服务器
    com.nimbusds.oauth2.sdk.Scope
public static Scope parse(String s) {
    if (s == null) {
        return null;
    } else {
        Scope scope = new Scope();
        if (s.trim().isEmpty()) {
            return scope;
        } else {
            StringTokenizer st = new StringTokenizer(s, " ,");

            while(st.hasMoreTokens()) {
                scope.add(new Scope.Value(st.nextToken()));
            }

            return scope;
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/425431.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号