假设我们的系统中有3个微服务,分别为business-provider-svc、business-consumer-svc、其他服务。
现在的需求是不允许其他服务或着直接调用business-provider-svc,只能通过business-consumer-svc间接调用。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Authorize {
// allowed consumers
String[] value();
}
public class AuthorizeInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Authorize authorize = handlerMethod.getMethod().getAnnotation(Authorize.class);
if (authorize == null) {
return true; // no need to authorize
}
String[] allowedHeaders = authorize.value();
String authzHeader = request.getHeader("Authorization");
if (StringUtils.isEmpty(authzHeader)) {
throw new RuntimeException("Missing Authorization http header");
}
if (!Arrays.asList(allowedHeaders).contains(authzHeader)) {
throw new RuntimeException("You do not have access to this service");
}
return true;
}
}
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthorizeInterceptor());
}
}
Controller
@RestController
@RequestMapping("/v1/business")
public class BusinessController {
@Autowired
private BusinessService businessService;
@GetMapping("/save")
@Authorize(value = {"business-consumer-svc"})
public BusinessData save(){
BusinessData businessData = new BusinessData();
businessData.setLogInfo("query salary " + System.currentTimeMillis());
businessData.setLogTime(new Date());
BusinessData saved = businessService.save(businessData);
return saved;
}
@GetMapping("/getList")
@Authorize(value = {"business-consumer-svc"})
public List<BusinessData> getList(){
List<BusinessData> list = businessService.getList();
return list;
}
}
Service
@Service
public class BusinessService {
@Autowired
private BusinessRepository businessRepository;
public BusinessData save(BusinessData businessData){
BusinessData saved = businessRepository.save(businessData);
return saved;
}
public List<BusinessData> getList(){
List<BusinessData> lists = new ArrayList<>();
Iterable<BusinessData> all = businessRepository.findAll();
all.forEach(b -> lists.add(b));
return lists;
}
}
Repository
public interface BusinessRepository extends CrudRepository<BusinessData,String> {
}
model
@NoArgsConstructor
@AllArgsConstructor
@Data
@Builder
@Entity(name = "business_data")
public class BusinessData {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "log_info")
private String logInfo;
@Column(name = "log_time")
private Date logTime;
}
pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
配置文件
server:
port: 8082
spring:
application:
name: business-provider-svc
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/boot_integrate_other
username: root
password: root
jpa:
show-sql: true
hibernate:
ddl-auto: update
@FeignClient(name = "business-provider-svc",path = "/v1/business",url = "http://localhost:8082")
public interface BusinessProviderClient {
@GetMapping("/save")
BusinessData save(@RequestHeader("Authorization") String authz);
@GetMapping("/getList")
List<BusinessData> getList(@RequestHeader("Authorization") String authz);
}
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private BusinessProviderClient businessProviderClient;
@GetMapping("/testAuth")
public List<BusinessData> testAuth(){
List<BusinessData> list = businessProviderClient.getList("business-consumer-svc");
return list;
}
@GetMapping("/testNoAuth")
public List<BusinessData> testNoAuth(){
List<BusinessData> list = businessProviderClient.getList("business-consumer-svc-2");
return list;
}
}
pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.xupengzhuang</groupId>
<artifactId>business-provider-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
配置文件
server:
port: 8081
spring:
application:
name: business-consumer-svc
代码全部编写完后,就可以启动两个module进行测试了。