Spring Cloud OAuth2.0安全之路(三) 搭建测试微服务
1.创建SpringBoot项目,导入相关的包,工程结构如下
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:
请求方式是Basic Auth username和password必须和数据库中名字一样
请求成功,然后拿着access_token去请求order服务
请求order服务 type类型是Bearer Token 然后将access_token粘贴进去
请求成功,接着再看看项目后台日志
order服务
price服务
可以看到,两个服务都是可以拿到用户信息
至此,一个简单的oauth框架搭建完毕。
第一次写博客,主要目的是强迫自己加深理解,如果文中有不对的地方,欢迎各大佬指教。
有兴趣一起学的小伙伴可以加好友一起学习。
源码地址:https://gitee.com/bigger-xu/oauthZuul
后续会研究一下异常信息的获取,包括自动刷新token等,等学明白再写。