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

时间:2014-06-20 09:37:06

标签: spring-mvc spring-security

我遇到了Spring MVC + Spring安全性问题(3.2.8版本)。好吧,我有一个 REST 服务,它以xml格式返回我的应用程序中存储的所有设备。这就是我所说的:

{baseUrl}/service/equipment

这是方法签名,返回EquipmentExchangeSet实体。该实体使用java xml绑定注释。

@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安全约束时,一切都像魅力一样,但是,我需要它们只让登录的用户访问服务。这就是我为Web服务配置Spring安全配置的方法:

<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(未授权)代码。有没有办法从服务中检索凭证或在相同的上下文中执行该请求?

1 个答案:

答案 0 :(得分:1)

我将重新设计Controller方法并拆分在服务中生成XML的实际逻辑。这样,您可以将服务注入其他控制器并调用它,而无需向同一应用程序实际发出额外请求。实施内部请求(例如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();
    }
}

这样,您不仅可以通过身份验证来规避整个问题,还可以使代码更具可重用性并消除错误。