IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> oauth2 通过SecurityContextHolder获取用户信息(二) -> 正文阅读

[开发测试]oauth2 通过SecurityContextHolder获取用户信息(二)

既上一篇获取用户信息,又找到了另一种获取用户信息的方法,在这做下介绍
本方法获取用户信息使用的是 token-info-uri
user-info-uri方式移步

资源服务配置文件

当使用token-info-uri时,默认user-info-uri不生效,loadBalanced:集群配置

security:
  oauth2:
    resource:
      loadBalanced: true
      user-info-uri: http://service-auth1/users/current
      token-info-uri: http://service-auth/oauth/check_token
    client:
      client-secret: 123456
      access-token-uri: http://service-auth/oauth/token
      grant-type: password,client_credentials,refresh_token,authorization_code
      scope: all
      client-id: client

资源服务器配置

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    /**
     * 资源服务器配置
     */
    @Resource
    private ResourceServerProperties resourceServerProperties;
    /**
     * 客户端属性
     */
    @Resource
    private OAuth2ClientProperties oAuth2ClientProperties;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/oauth/**").permitAll()
                .anyRequest().authenticated();//任何连接只要认证后放行
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources
                .tokenServices(tokenServices())

                // 无效token异常类重写
                .authenticationEntryPoint(new CustomAuthenticationEntryPoint())
                // 权限不足异常类重写
                .accessDeniedHandler(new CustomAccessDeniedHandler());
    }

    /**
     * 默认资源服务器获取当前登录用户的username
     * 添加该方法后可以获取到与授权服务器一样的用户信息
     */
    @Bean
    @Primary
    public ResourceServerTokenServices tokenServices() {
        RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
        remoteTokenServices.setCheckTokenEndpointUrl(resourceServerProperties.getTokenInfoUri());
        remoteTokenServices.setClientId(oAuth2ClientProperties.getClientId());
        remoteTokenServices.setClientSecret(oAuth2ClientProperties.getClientSecret());
        remoteTokenServices.setRestTemplate(restTemplate());

        DefaultAccessTokenConverter defaultAccessTokenConverter = new DefaultAccessTokenConverter();
        defaultAccessTokenConverter.setUserTokenConverter(new CommonUserConverter());
        remoteTokenServices.setAccessTokenConverter(defaultAccessTokenConverter);
        return remoteTokenServices;
    }

    /**
     * 创建新的restTemplate
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
        List<HttpMessageConverter<?>> convertersValid = new ArrayList<>();
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof MappingJackson2HttpMessageConverter || converter instanceof MappingJackson2XmlHttpMessageConverter) {
                continue;
            }
            convertersValid.add(converter);
        }
        convertersValid.add(new FastJsonHttpMessageConverter());
        restTemplate.setMessageConverters(convertersValid);
        return restTemplate;
    }
}

重写UserAuthenticationConverter

/**
 * 根据Token获取用户信息 与DefaultUserAuthenticationConverter同集成,优先该方法
 * @author king
 */
public class CommonUserConverter implements UserAuthenticationConverter {

    private static final String N_A = "N/A";

    /**
     * 将授权信息返回到资源服务
     *
     * @param authentication
     * @return
     */
    @Override
    public Map<String, ?> convertUserAuthentication(Authentication authentication) {
        Map<String, Object> authMap = new LinkedHashMap<>();
        authMap.put(USERNAME, authentication.getName());
        if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) {
            authMap.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities()));
        }
        return authMap;
    }

    /**
     * 获取用户认证信息
     *
     * @param map
     * @return
     */
    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        if (map.containsKey(USERNAME)) {
            Collection<? extends GrantedAuthority> authorities = getAuthorities(map);

            String userId = (String) map.get("id");
            String username = (String) map.get("username");
            LoginUser user = new LoginUser(userId, username, N_A, true, true, true, true, authorities);
            return new UsernamePasswordAuthenticationToken(user, N_A, authorities);
        }
        return null;
    }

    /**
     * 获取权限资源信息
     *
     * @param map
     * @return
     */
    private Collection<? extends GrantedAuthority> getAuthorities(Map<String, ?> map) {
        Object authorities = map.get(AUTHORITIES);
        if (authorities instanceof String) {
            return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities);
        }
        if (authorities instanceof Collection) {
            return AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString((Collection<?>) authorities));
        }
        throw new IllegalArgumentException("Authorities must be either a String or a Collection");
    }
}

如果出现问题

import org.springframework.security.oauth2.provider.token.RemoteTokenServices;

点进RemoteTokenServices中,打断点测试
在这里插入图片描述
在这里插入图片描述

最后

在配置restTemplate的时候要清掉自带的xml返回值类型,要不然restTemplate会只得到xml参数,导致解析成map时里面全部为String,导致验证失败
这个方法配置起来比较麻烦,但是还是可以用的,如果嫌麻烦,该方法比较简单 user-info-uri方式移步

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:47:46  更:2022-04-09 18:48:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:46:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码