grpc之java使用拦截器实现权限验证
在前面java实现的简单调用基础上增加拦截器实现请求权限验证。
- 新建intercept目录新增服务段和客户端拦截器
ServerIntercept.java
package com.wms.inercept;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
public class ServerIntercept implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall, Metadata metadata, ServerCallHandler<ReqT, RespT> serverCallHandler) {
System.out.println("每次请求都要经过我");
Metadata.Key<String> accessToken =
Metadata.Key.of("accessToken", Metadata.ASCII_STRING_MARSHALLER);
System.out.println(metadata.get(accessToken));
return serverCallHandler.startCall(serverCall, metadata);
}
}
ClientIntercept.java
package com.wms.inercept;
import io.grpc.*;
public class ClientIntercept implements ClientInterceptor {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
CallOptions callOptions, Channel next) {
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
/* put custom header */
Metadata.Key<String> accessToken =
Metadata.Key.of("accessToken", Metadata.ASCII_STRING_MARSHALLER);
headers.put(accessToken, "customRequestValue");
super.start(new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(responseListener) {
@Override
public void onHeaders(Metadata headers) {
/**
* if you don't need receive header from server,
* you can use {@link io.grpc.stub.MetadataUtils#attachHeaders}
* directly to send header
*/
System.out.println("header received from server:" + headers);
super.onHeaders(headers);
}
}, headers);
}
};
}
}
然后启动服务端和客户端,输出如图
2. pom文件中新增2各依赖
<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.16.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.40</version>
</dependency>
一个是解密解密库,一个是处理json. 3. 新建User和token验证返回类 User.java
package com.wms.model;
public class User {
private String userName;
private String passWord;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
}
TokenResponse.java
package com.wms.model;
public class TokenResponse {
private boolean success;
private String message;
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
- 在拦截器目录添加token检查方法
package com.wms.inercept;
import com.alibaba.fastjson2.JSON;
import com.wms.model.Carrier;
import com.wms.model.TokenResponse;
import com.wms.model.User;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import java.util.Arrays;
public class Token {
public TokenResponse check(String accessToken){
// String token = Hex.encodeHexString(Base64.encodeBase64String("{\"userName\":\"wms\",\"passWord\":\"123456\"}".getBytes()).getBytes());
TokenResponse tokenResponse = new TokenResponse();
if(accessToken.isEmpty()){
tokenResponse.setSuccess(false);
tokenResponse.setMessage("请添加授权token");
return tokenResponse;
}
String jsonStr = "";
User user = new User();
try {
jsonStr = new String(Base64.decodeBase64(Hex.decodeHex(accessToken)));
user = JSON.parseObject(jsonStr, User.class);
} catch (Exception e) {
tokenResponse.setSuccess(false);
tokenResponse.setMessage(e.getMessage());
return tokenResponse;
}
if(user.getUserName().equals("wms") && user.getPassWord().equals("123456")){
tokenResponse.setSuccess(true);
tokenResponse.setMessage("验证通过");
}
return tokenResponse;
}
}
- 客户端和服务端拦截器修改如下 ClientIntercept.java 请求前添加token
headers.put(accessToken, "65794a3163325679546d46745a534936496e647463794973496e426863334e5862334a6b496a6f694d54497a4e445532496e303d");
ServerIntercept.java 接收验证token
Token token = new Token();
TokenResponse b = token.check(metadata.get(accessToken));
if(!b.isSuccess()){
serverCall.close(Status.UNAUTHENTICATED,metadata);
}
- 返回结果
- 用php请求,和前面请求golang一样,只是地址换一下
$clientJava = new Carrier\CarrierClient('192.168.2.127:50052', [
'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
$carrierRequest = new Carrier\CarrierRequest();
$carrierRequest->setName("e邮宝");
$meaData = array(
'accessToken' => array("65794a3163325679546d46745a534936496e647463794973496e426863334e5862334a6b496a6f694d54497a4e445532496e303d")
);
list($replyj, $statusj) = $clientJava->GetCarrier($carrierRequest,$meaData)->wait();
if($statusj->code === 0){
print_r($replyj->getName());
print_r($replyj->getId());
print_r($statusj->code);
print_r(json_encode($replyj));
print_r(json_encode($statusj));
}else{
print_r($statusj->code);
print_r($statusj->details);
}