SpringCloudAlibaba+Zuul+OAuth2 (二) 搭建资源微服务

接上一篇 我们已经搭建好认证微服务 下面我们开始搭建资源微服务 上一篇 假设我有一个geme_client,那么现在我们需要来搭建game-service这个微服务 现在开始创建 maven springboot工程 pom文件依赖跟上一篇依赖一样 步骤略

假设你已经搭建好上述工程(就很简单一个springboot工程所以此处略)

1.写资源服务配置 

/**
 * @Description auth资源配置
 * @Date 2020/6/24 23:46
 * @Author Jax
 */
@Configuration
@EnableResourceServer
public class OAuthResourceServiceCofig extends ResourceServerConfigurerAdapter {
    /**
     * 配置 resourceId 即告诉认证服务器 我就是 game-service
     * @param resources
     * @throws Exception
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId("game-service");
    }

    /**
     * 默认所有的请求都需要验证token
     * 根据自己项目实际情况来配置
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //我这里就意思意思一下 假设配置token,test开头的url不需要验证,多个逗号隔开
                .antMatchers("/token/*","/test/*")
                //剩下的都需要拦截
                .permitAll().anyRequest().authenticated();
    }
}

2.令牌应该怎么来验证 下面来写代码

/**
 * @Description 配置资源服务器Web配置
 * @Date 2020/6/25 00:00
 * @Author Jax
 */
@Configuration
@EnableWebSecurity
public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     * 声明资源服务器令牌服务
     * @return
     */
    @Bean
    public ResourceServerTokenServices tokenServices(){
        RemoteTokenServices tokenServices =  new RemoteTokenServices();
        tokenServices.setClientId("game_client");//认证服务器认识的client
        tokenServices.setClientSecret("123456");//认证服务器认识的client secret
        tokenServices.setCheckTokenEndpointUrl("http://localhost:8088/oauth/check_token");//认证服务器验证token url
        return tokenServices;
    }

    /**
     * 告诉认证服务器对应的令牌-->>用户信息
     * 暴露AuthenticationManager
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
        authenticationManager.setTokenServices(tokenServices());
        return authenticationManager;
    }

}

3.如何让自己的应用(game-service)知道我认证的这个令牌的用户信息呢(带着令牌来访问服务 我怎么知道这是哪一个用户),之前我们已经获取到token 在game-service中写一个控制器 来测试一下

@RestController
public class HelloController {
    /**
    * 只需要在需要用户信息的地方添加@AuthenticationPrincipal 就可以获取当前令牌的用户名了
    * 目前这里只能是 String username 需要获取更复杂的用户信息 我们放第4步来实现
    **/
    @GetMapping("/user/test")
    public String getUserMsg(@AuthenticationPrincipal String username){
        System.out.println("------->>>获取到的用户用户username="+username);
        return username;
    }
}

向认证服务器申请令牌

使用postman访问 game-service test测试接口

查看控制台

至此 简单的资源服务器 就搭建OK了!

4.如何获取更复杂的用户信息 上面只是单纯的用户名 这样的话 我每一次 需要用户信息 都需要根据用户名去数据库查询~怎么直接从令牌里面获取复杂的用户信息呢?下面来写代码 新建一个UserDetailsServiceImpl

/**
 * @Description 获取用户信息
 * @Date 2020/6/25 12:31
 * @Author Jax
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //TODO 根据用户名 去数据库查询当前用户对象  CurrentUser为我们自定义的返回用户对象
        CurrentUser user = new CurrentUser();
        user.setId(100L);
        user.setUsername("abababab");
        ........
        return user;
    }
}

从上面 我们可以看到loadUserByUsername返回的是一个UserDetails 如果需要返回我们自定义的CurrentUser 我们来实现UserDetails

/**
 * @Description 当前操作用户 这里我直接返回都是true 根据自己项目情况来返回下面这些方法返回的boolean 类型
 * @Date 2020/6/25 14:51
 * @Author Jax
 */
public class CurrentUser implements UserDetails {
    //添加自己需要的用户信息字段 我这里就加一个用户id
    private Long id;
    private String username;
    private String password;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        //return null;
        //方便测试 使用这个方法 把字符串转换成需要的权限集合
        return AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN");
    }

    //账号是否过期
    @Override
    public boolean isAccountNonExpired() {
        //TODO 应该从数据库去查询 来返回
        return true;
    }

    //是否锁定
    @Override
    public boolean isAccountNonLocked() {
        //TODO 应该从数据库去查询 来返回
        return true;
    }

    //密码是否过期
    @Override
    public boolean isCredentialsNonExpired() {
        //TODO 应该从数据库去查询 来返回
        return true;
    }

    //账号是否可用
    @Override
    public boolean isEnabled() {
        //TODO 应该从数据库去查询 来返回
        return true;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

完成上面的代码编写 这个时候我们需要告知用我们写的UserDetailsServiceImpl来返回用户信息 在第 2 步的基础上 添加配置

/**
 * @Description 配置资源服务器Web配置
 * @Date 2020/6/25 00:00
 * @Author Jax
 */
@Configuration
@EnableWebSecurity
public class OAuth2WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    //注入刚刚我们自定义的UserDetailsServiceImpl
    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    /**
     * 声明资源服务器令牌服务
     * @return
     */
    @Bean
    public ResourceServerTokenServices tokenServices(){
        RemoteTokenServices tokenServices =  new RemoteTokenServices();
        tokenServices.setClientId("game_client");//认证服务器认识的client
        tokenServices.setClientSecret("123456");//认证服务器认识的client secret
        tokenServices.setCheckTokenEndpointUrl("http://localhost:8088/oauth/check_token");//认证服务器验证token url
        //配置返回userTokenConverter为我们自定义的UserDetails信息
        tokenServices.setAccessTokenConverter(getAccessTokenConverter());
return tokenServices;
    }

    /**
     * 告诉认证服务器对应的令牌-->>用户信息
     * 暴露AuthenticationManager
     * @return
     * @throws Exception
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
        authenticationManager.setTokenServices(tokenServices());
        return authenticationManager;
    }

    private AccessTokenConverter getAccessTokenConverter(){
        DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
        DefaultUserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter();
        //默认这个UserDetailsService是null 
        userTokenConverter.setUserDetailsService(userDetailsService);
        accessTokenConverter.setUserTokenConverter(userTokenConverter);
        return accessTokenConverter;
    }

}

以上步骤完成 这个时候就可以去获取我们自定义的CurrentUser 相关信息了 在第 步我们获取当前用户的基础上

@RestController
public class HelloController {
    /**
     * 默认不配置 只能获取用户名 @AuthenticationPrincipal String username
     * 添加了OAuth2WebSecurityConfig中tokenServices.setAccessTokenConverter(getAccessTokenConverter());配置
     * 可以直接获取当前用户 如果只想获取当前用户的id 或 其它字段的值 可以使用spring表达式来获取(可以获取这个对象的任何属性)
     * 比如获取用户id  @AuthenticationPrincipal(expression = "#this.id") Long userId
     * @return
     */
    @GetMapping("/user/test")
    public String getUserMsg(@AuthenticationPrincipal CurrentUser user){
        System.out.println("------->>>获取到的用户用户"+ JSON.toJSONString(user));
        return "OK";
    }
}

获取复杂的用户信息 配置到此结束!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值