Skip to content

Commit

Permalink
feat: add RestExtension spi
Browse files Browse the repository at this point in the history
  • Loading branch information
Similarityoung committed Nov 21, 2024
1 parent accf9ce commit 4d9200f
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@

package org.apache.dubbo.rest.demo;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class ResourceApplication {
public static void main(String[] args) {
SpringApplication.run(ResourceApplication.class, args);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.dubbo.rest.demo.controller;

import jakarta.annotation.Resource;

import org.apache.dubbo.rest.demo.service.HelloService;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloController {

@Resource
private HelloService helloService;

@PostMapping("/hello/{name}")
public String hello(@PathVariable String name) {
return helloService.sayHello(name);
}
}
///*
// * Licensed to the Apache Software Foundation (ASF) under one or more
// * contributor license agreements. See the NOTICE file distributed with
// * this work for additional information regarding copyright ownership.
// * The ASF licenses this file to You under the Apache License, Version 2.0
// * (the "License"); you may not use this file except in compliance with
// * the License. You may obtain a copy of the License at
// *
// * http://www.apache.org/licenses/LICENSE-2.0
// *
// * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and
// * limitations under the License.
// */
//
//package org.apache.dubbo.rest.demo.controller;
//
//import jakarta.annotation.Resource;
//
//import org.apache.dubbo.rest.demo.service.HelloService;
//
//import org.springframework.web.bind.annotation.PathVariable;
//import org.springframework.web.bind.annotation.PostMapping;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RestController;
//
//@RestController
//@RequestMapping("/api")
//public class HelloController {
//
// @Resource
// private HelloService helloService;
//
// @PostMapping("/hello/{name}")
// public String hello(@PathVariable String name) {
// return helloService.sayHello(name);
// }
//}
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,42 @@

package org.apache.dubbo.rest.demo.filter;

import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;

import jakarta.servlet.Filter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import org.apache.dubbo.rpc.protocol.tri.rest.filter.RestExtension;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;

public class OAuthFilter implements Filter {
import java.io.IOException;

public class OAuthFilter implements Filter, RestExtension {

@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
JwtAuthenticationToken authentication = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
public String[] getPatterns() {
return new String[] { "/**" }; // Intercept all requests
}

if (authentication == null || !authentication.isAuthenticated()) {
throw new RpcException("Unauthorized request - authentication token is missing or invalid");
@Override
public void doFilter(
ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws ServletException {
// Check if the request is authorized
JwtAuthenticationToken jwtAuthenticationToken = (JwtAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
if (jwtAuthenticationToken == null) {
throw new ServletException("Unauthorized");
}
}

return invoker.invoke(invocation);
@Override
public int getPriority() {
return -200;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.rest.demo.service.HelloService;

import org.springframework.stereotype.Service;

@DubboService
@Service
public class HelloServiceImpl implements HelloService {

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#

OAuthFilter=org.apache.dubbo.rest.demo.filter.OAuthFilter
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

server:
port: 9001

Expand All @@ -24,15 +23,15 @@ spring:
dubbo:
application:
name: ${spring.application.name}
protocol: tri
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
protocol:
name: tri # Use the Triple protocol
port: 50051 # Service port (adjust as needed)
triple:
verbose: true # Enable verbose mode
provider:
filter: OAuthFilter # Register the OAuthFilter globally as a filter


logging:
level:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,92 @@
*/

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.apache.dubbo.rest.demo.ResourceApplication;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.rest.demo.service.HelloService;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.apache.dubbo.rpc.RpcContext;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestClientResponseException;

import java.util.Base64;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(classes = ResourceApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableDubbo
@RunWith(SpringRunner.class)
public class ResourceServerTest {

@LocalServerPort
private int port;
// @LocalServerPort
// private int port;

@DubboReference(url = "tri://localhost:50051")
private HelloService helloService;

private final String clientId = "49fd8518-12eb-422b-9264-2bae0ab89f66";
private final String clientSecret = "H3DTtm2fR3GRAdr4ls1mcg";

// @Test
// public void testGetUserEndpoint() {
// String credentials = clientId + ":" + clientSecret;
// String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes());
//
// // build RestClient request
// RestClient restClient = RestClient.builder().build();
// String url = "http://localhost:" + 9000 + "/oauth2/token";
//
// try {
// // make a post request
// String response = restClient.post()
// .uri(url)
// .header(HttpHeaders.AUTHORIZATION, "Basic " + encodedCredentials)
// .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
// .body("grant_type=client_credentials&scope=read")
// .retrieve()
// .body(String.class);
//
// System.out.println("Access Token Response: " + response);
//
// ObjectMapper objectMapper = new ObjectMapper();
// JsonNode jsonNode = objectMapper.readTree(response);
// String accessToken = jsonNode.get("access_token").asText();
//
// System.out.println("accessToken: " + accessToken);
// // Use the access token to authenticate the request to the /user endpoint
// assert accessToken != null;
// String userUrl = "http://localhost:" + port + "/api/hello/World";
// try {
// String userResponse = restClient.post()
// .uri(userUrl)
// .header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
// .retrieve()
// .body(String.class);
//
// System.out.println("User Response: " + userResponse);
// assertEquals("Hello, World", userResponse, "The response should be 'Hello,user!'");
// } catch (RestClientResponseException e) {
// System.err.println("Error Response: " + e.getResponseBodyAsString());
// }
//
// } catch (JsonProcessingException e) {
// throw new RuntimeException(e);
// }
// }

@Test
public void testGetUserEndpoint() {
public void testHelloService() {

System.out.println("helloService: " + helloService.sayHello("World"));

String credentials = clientId + ":" + clientSecret;
String encodedCredentials = Base64.getEncoder().encodeToString(credentials.getBytes());

Expand All @@ -61,32 +119,21 @@ public void testGetUserEndpoint() {
.retrieve()
.body(String.class);

System.out.println("Access Token Response: " + response);

ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(response);
String accessToken = jsonNode.get("access_token").asText();

System.out.println("accessToken: " + accessToken);
// Use the access token to authenticate the request to the /user endpoint
assert accessToken != null;
String userUrl = "http://localhost:" + port + "/api/hello/World";
try {
String userResponse = restClient.post()
.uri(userUrl)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
.retrieve()
.body(String.class);

System.out.println("User Response: " + userResponse);
assertEquals("Hello, World", userResponse, "The response should be 'Hello,user!'");
} catch (RestClientResponseException e) {
System.err.println("Error Response: " + e.getResponseBodyAsString());
}

RpcContext.getContext().setAttachment("Authorization", "Bearer " + accessToken);

assertEquals("Hello, World", helloService.sayHello("World"), "The response should be 'Hello, World'");
} catch (JsonMappingException e) {
throw new RuntimeException(e);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}


}
}

0 comments on commit 4d9200f

Please sign in to comment.