接上一篇 我们已经搭建好认证微服务 下面我们开始搭建资源微服务 上一篇 假设我有一个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*/@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.resourceId("game-service");}/*** 默认所有的请求都需要验证token* 根据自己项目实际情况来配置* @param http* @throws Exception*/@Overridepublic 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*/@Beanpublic ResourceServerTokenServices tokenServices(){RemoteTokenServices tokenServices = new RemoteTokenServices();tokenServices.setClientId("game_client");//认证服务器认识的clienttokenServices.setClientSecret("123456");//认证服务器认识的client secrettokenServices.setCheckTokenEndpointUrl("http://localhost:8088/oauth/check_token");//认证服务器验证token urlreturn tokenServices;}/*** 告诉认证服务器对应的令牌-->>用户信息* 暴露AuthenticationManager* @return* @throws Exception*/@Bean@Overridepublic 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 {@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic 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 {//添加自己需要的用户信息字段 我这里就加一个用户idprivate Long id;private String username;private String password;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {//return null;//方便测试 使用这个方法 把字符串转换成需要的权限集合return AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN");}//账号是否过期@Overridepublic boolean isAccountNonExpired() {//TODO 应该从数据库去查询 来返回return true;}//是否锁定@Overridepublic boolean isAccountNonLocked() {//TODO 应该从数据库去查询 来返回return true;}//密码是否过期@Overridepublic boolean isCredentialsNonExpired() {//TODO 应该从数据库去查询 来返回return true;}//账号是否可用@Overridepublic boolean isEnabled() {//TODO 应该从数据库去查询 来返回return true;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}@Overridepublic String getUsername() {return username;}public void setUsername(String username) {this.username = username;}@Overridepublic 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@Autowiredprivate UserDetailsServiceImpl userDetailsService;/*** 声明资源服务器令牌服务* @return*/@Beanpublic ResourceServerTokenServices tokenServices(){RemoteTokenServices tokenServices = new RemoteTokenServices();tokenServices.setClientId("game_client");//认证服务器认识的clienttokenServices.setClientSecret("123456");//认证服务器认识的client secrettokenServices.setCheckTokenEndpointUrl("http://localhost:8088/oauth/check_token");//认证服务器验证token url//配置返回userTokenConverter为我们自定义的UserDetails信息tokenServices.setAccessTokenConverter(getAccessTokenConverter());
return tokenServices;}/*** 告诉认证服务器对应的令牌-->>用户信息* 暴露AuthenticationManager* @return* @throws Exception*/@Bean@Overridepublic 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 相关信息了 在第 3 步我们获取当前用户的基础上
@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";}
}
获取复杂的用户信息 配置到此结束!