Spring Cloud OAuth2.0安全之路(三) 搭建测试微服务

1.创建SpringBoot项目,导入相关的包,工程结构如下

SpringCloud OAuth2 yaml 解密配置_ci

2.pom文件代码示例:

<parent>
		<artifactId>cloud-root</artifactId>
		<groupId>com.cto.cloud</groupId>
		<version>1.0-SNAPSHOT</version>
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

parent参考 Spring Cloud OAuth2.0安全之路(一) 搭建OAuth2.0服务

3.主要配置

@RestController
@RequestMapping("/orders")
@Slf4j
public class OrderController {
	
	@Autowired
	private OAuth2RestTemplate restTemplate;
	
	@PostMapping
	@PreAuthorize("hasRole('ROLE_ADMIN')")
	public OrderInfo create(@RequestBody OrderInfo info, @AuthenticationPrincipal String username){
		log.info("user is " + username);
		return info;
	}
	
	@GetMapping("/{id}")
	public OrderInfo getInfo(@PathVariable Long id, @AuthenticationPrincipal String username) {
		log.info("user is " + username);
		log.info("orderId is " + id);
		PriceInfo price = restTemplate.getForObject("http://localhost:9070/prices/"+id, PriceInfo.class);
		log.info("price is "+price.getPrice());
		OrderInfo info = new OrderInfo();
		info.setId(id);
		info.setProductId(id * 5);
		return info;
	}

}

此处请求价格服务的restTemplate不能直接使用cloud的restTemplate,而是使用OAuth2RestTemplate,是OAuth2提供的,它会在请求的时候将令牌自动放入,不需要我们其他的操作

OAuth2RestTemplate配置如下:

@Configuration
public class ActuatorSecurityConfig extends ResourceServerConfigurerAdapter {

	@Override
	public void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
			.anyRequest().authenticated();
	}
}

Application配置

@Configuration
@SpringBootApplication
@EnableResourceServer
public class OrderApplication {

	@Bean
	public OAuth2RestTemplate oauth2RestTemplate(OAuth2ProtectedResourceDetails resource, OAuth2ClientContext context) {
		return new OAuth2RestTemplate(resource, context);
	}

	public static void main(String[] args) {
		SpringApplication.run(OrderApplication.class, args);
	}

}

yml配置

server:
  port: 9080
  
security:
  oauth2:
    client:
      client-id: order
      client-secret: 123456
    resource:
      jwt:
        key-uri: http://localhost:9090/oauth/token_key
        
spring:
  application:
    name: order

4.价格服务

价格服务没什么特殊的配置,只是一个简单的get方法,代码如下:

@RestController
@RequestMapping("/prices")
@Slf4j
public class PriceController {
	
	@GetMapping("/{id}")
	public PriceInfo getPrice(@PathVariable Long id, @AuthenticationPrincipal String username) {
		log.info("productId is "+id);
		log.info("user is "+ username);
		PriceInfo info = new PriceInfo();
		info.setId(id);
		info.setPrice(new BigDecimal(100));
		return info;
	}

}

@AuthenticationPrincipal注解是用来获取令牌中的信息
yml配置如下:

server:
  port: 9070
  
security:
  oauth2:
    client:
      client-id: price
      client-secret: 123456
    resource:
      jwt:
        key-uri: http://localhost:9090/oauth/token_key

5.测试

首先用户表添加一条数据,sql:

CREATE TABLE `front_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID编号',
  `uuid` varchar(64) NOT NULL COMMENT 'UUID',
  `create_time` datetime NOT NULL COMMENT '添加时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `status` char(1) DEFAULT NULL COMMENT '用户状态(0锁定1正常)',
  `user_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户名',
  `password` varchar(32) DEFAULT NULL COMMENT '密码校验规则md5(md5(password)+salt)',
  `salt` varchar(20) DEFAULT NULL COMMENT '盐值',
  `nick_name` varchar(50) DEFAULT NULL COMMENT '昵称',
  `avator` varchar(250) DEFAULT NULL COMMENT '用户头像',
  `sex` varchar(10) DEFAULT NULL COMMENT '性别',
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '电子邮箱',
  `mobile` varchar(255) DEFAULT NULL COMMENT '联系电话',
  `last_login_time` datetime DEFAULT NULL COMMENT '最后一次登录时间',
  `last_login_ip` varchar(100) DEFAULT NULL COMMENT '最后一次登录IP',
  `login_count` int(11) DEFAULT NULL COMMENT '登录次数',
  `delete_flag` char(1) DEFAULT '0' COMMENT '删除状态',
  PRIMARY KEY (`id`),
  UNIQUE KEY `UN_UUID` (`uuid`) USING BTREE,
  UNIQUE KEY `UN_NAME` (`user_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='前台用户表';


INSERT INTO `cloud-security`.`front_user`(`id`, `uuid`, `create_time`, `update_time`, `status`, `user_name`, `password`, `salt`, `nick_name`, `avator`, `sex`, `email`, `mobile`, `last_login_time`, `last_login_ip`, `login_count`, `delete_flag`) VALUES (1, 'f519f029e0a84c138f69c3f009f03937', '2020-01-07 08:01:47', NULL, '1', 'admin', '123456', '3160', '伟一哥', NULL, NULL, NULL, NULL, NULL, NULL, 0, '0');

依次启动服务,auth>zuul>order>price

获取token:

SpringCloud OAuth2 yaml 解密配置_ci_02


请求方式是Basic Auth username和password必须和数据库中名字一样

SpringCloud OAuth2 yaml 解密配置_ci_03


请求成功,然后拿着access_token去请求order服务

SpringCloud OAuth2 yaml 解密配置_java_04


请求order服务 type类型是Bearer Token 然后将access_token粘贴进去

SpringCloud OAuth2 yaml 解密配置_java_05


请求成功,接着再看看项目后台日志

order服务

SpringCloud OAuth2 yaml 解密配置_spring_06


price服务

SpringCloud OAuth2 yaml 解密配置_spring_07


可以看到,两个服务都是可以拿到用户信息

至此,一个简单的oauth框架搭建完毕。

第一次写博客,主要目的是强迫自己加深理解,如果文中有不对的地方,欢迎各大佬指教。
有兴趣一起学的小伙伴可以加好友一起学习。

源码地址:https://gitee.com/bigger-xu/oauthZuul

后续会研究一下异常信息的获取,包括自动刷新token等,等学明白再写。