spring-mvc - 获取当前凭据以访问其他 REST 服务

标签 spring-mvc spring-security

我在使用 Spring MVC + Spring security(均为 3.2.8 版本)时遇到问题。嗯,我有一个 REST 服务,它以 xml 格式返回存储在我的应用程序中的所有设备。我就是这样调用它的:

{baseUrl}/service/equipment

这就是方法签名,其中返回了一个 EquipmentExchangeSet 实体。此实体使用 java xml 绑定(bind)注释。

@RequestMapping(value = "equipment", method = RequestMethod.GET, headers = XML_JSON_HEADERS, produces = {
        XML, JSON })
@ResponseBody
public EquipmentExchangeSet getEquipment() {

}

我现在要做的是获取该文件并使用 xsl 样式对其进行处理,以便稍后获得输出 HTML 或 PDF。所以我实现了这个 Spring 服务:

@RequestMapping(value = "/equipment/format/html", method = RequestMethod.GET, produces = { MediaType.TEXT_HTML_VALUE })
@ResponseBody
public String getEquipmentHTML() throws TransformerException, IOException {
    /* Create a TransformerFactory object */
    TransformerFactory tFactory = TransformerFactory.newInstance();
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    /* Get the incoming XSLT file */
    Transformer transformer = tFactory.newTransformer(new StreamSource(
            "equipment.xsl"));
    URL xmlServiceUrl = new URL(
            "http://localhost:8080/myapp/service/equipment/");
    /* Get the XML file and apply the XSLT transformation to convert to HTML */
    transformer.transform(new StreamSource(xmlServiceUrl.openStream()),
            new StreamResult(os));
    return os.toString();
}

这会访问第一个服务的 url,获取 xml 内容并对其进行处理以获得时尚的输出 HTML 内容。删除 Spring 安全约束时,一切都像魅力一样,但是,我需要它们只让登录用户访问服务。这就是我的 spring 安全配置为 web 服务配置的方式:

<http entry-point-ref="restAuthenticationEntryPoint" pattern="/service/**"
    use-expressions="true">
    <intercept-url pattern="/service/**" access="isAuthenticated()" />

    <form-login authentication-success-handler-ref="restSuccessHandler"
        authentication-failure-handler-ref="restFailureHandler"
        login-processing-url="/service/j_spring_security_check" />

    <logout />
</http>

此配置仅允许已通过身份验证的用户访问。但是,当我尝试从 Spring 服务本身发出请求时,我得到一个 401(未授权) 代码。有没有办法从服务中检索凭据或在相同的上下文中执行该请求?

最佳答案

我会重新设计 Controller 方法并拆分在服务中生成 XML 的实际逻辑。这样你就可以在另一个 Controller 中注入(inject)服务并调用它,而无需实际向同一个应用程序发出额外的请求。发出像 localhost:8080/... 这样的内部请求实际上是一种不好的做法,因为一旦您部署在不同的端口上,该代码就会中断。

@Service
public class EquipmentService {

    public InputStream getEquipmentAsXml(){
        ....
    }
}

@Controller
public class EquipmentController {

    @Autowired
    private EquipmentService equipmentService;

    @RequestMapping(value = "/equipment/format/html", method = RequestMethod.GET, produces = { MediaType.TEXT_HTML_VALUE })
    @ResponseBody
    public String getEquipmentHTML() throws TransformerException, IOException {
        /* Create a TransformerFactory object */
        TransformerFactory tFactory = TransformerFactory.newInstance();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        /* Get the incoming XSLT file */
        Transformer transformer = tFactory.newTransformer(new StreamSource(
        "equipment.xsl"));

        transformer.transform(new StreamSource(equipmentService.getEquipmentAsXml()),
        new StreamResult(os));
        return os.toString();
    }
}

这样您不仅可以绕过身份验证的整个问题,还可以使您的代码更可重用并消除错误。

关于spring-mvc - 获取当前凭据以访问其他 REST 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24324233/

相关文章:

java - 如何使用 Spring RestTemplate 将 Riot Api 请求映射到对象

java - 将 Servlet 上下文参数传递给 Spring MVC Controller

java - @Service 的 Spring @ComponentScan

java - Spring @RequestParam DateTime 格式为 ISO 8601 日期可选时间

eclipse - 无法在Linux服务器上运行的tomcat上启动war应用程序

java - 具有 spring 安全性的程序化记住我

java - 使用 RequestBody 注释时的映射不明确

Spring 安全 5 : providing roles for OAuth2 authenticated users

grails - BootStrap.groovy 中的语法错误

spring - 如何使用 Spring Security 通知用户另一个 session ?