web-services - 使用 INI 通过 Apache Shiro 保护 Apache CXF Web 服务

标签 web-services cxf shiro

这里迫切需要帮助来保护简单的 Apache CXF Web 服务。使用 Spring Security 的尝试没有带我去任何地方,所以我需要找到不同的策略。这是为了对为我们的一些客户实现的遗留 Java 服务实现授权。

这个简单的 Apache CXF Web 服务是使用 Maven 的 cxf-jaxws-javafirst 原型(prototype)创建的。 它生成了 web.xml 和 beans.xml 文件以及示例代码。除了保持默认状态的 beans.xml 之外,我还修改了这些实体,如下所示:

web.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">


<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/beans.xml</param-value>
    </context-param>
     <context-param>
     <param-name>shiroConfigLocations</param-name>
        <param-value>WEB-INF/shiro.ini</param-value>
      </context-param>  

     <filter>
        <filter-name>ShiroFilter</filter-name>
        <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>       
    </filter>

    <filter-mapping>
        <filter-name>ShiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>      
        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
    </listener> 

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>      
    </listener>


    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <display-name>CXF Servlet</display-name>
        <servlet-class>
            org.apache.cxf.transport.servlet.CXFServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

我的 Shiro.ini 文件如下所示:

# =======================
# Shiro INI configuration
# =======================

[main]
authc = org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter

[users]
o = o, OPERATOR
a = a, ADMIN
s = s, SUPERVISOR

[roles]
SUPERVISOR = *
ADMIN = sayHiAdmin
OPERATOR = deleteAccounts

我的简单网络服务代码如下:

import javax.jws.WebService;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.subject.Subject;

@WebService(endpointInterface = "org.myCo.com.CxfShiroSecuredService.HelloWorld")
public class HelloWorldImpl implements HelloWorld {

    public String sayHi(String text) {              

        if (isAuthorized("sayHi")) {
            return "Successfully said hi " + text;
        }               

        if (hasRole("OPERATOR")){
            return "User is OPERATOR";
        }
        if (hasRole("ADMIN")){
            return "User is OPERATOR";
        }
        throw new UnauthorizedException("Logged user does not have OPERATOR's permission");                             
    }    

    public String sayHiAdmin(String text) {         

        if (isAuthorized("sayHiAdmin")) {
            return "Successfully said hi Admin " + text;
        }               

        throw new UnauthorizedException("Logged user does not have ADMIN permission");
    }

    public String deleteAccounts(String text) {             

        if (isAuthorized("deleteAccounts")) {
            return "Successfully deleted accounts " + text;
        }               

        throw new UnauthorizedException("Logged user does not have SUPERVISOR permission");
    }

    private Boolean isAuthorized(String operation){
        Subject currentUser = SecurityUtils.getSubject();       
        return currentUser.isPermitted(operation);  //currentUser.isAuthenticated(); // && currentUser.isPermitted(operation);      
    }

    private Boolean hasRole(String role){
        Subject currentUser = SecurityUtils.getSubject();       
        return currentUser.hasRole(role);       
    }
}

我有一个 C# 测试客户端,它在调用 Web 服务之前在 SOAP header 中传递身份验证信息,如下所示:

 private void OnButtonClick(object sender, RoutedEventArgs e)
        {
            var client = new HelloWorldClient();
            var response = "";

            using (new OperationContextScope(client.InnerChannel))
            {
                var httpRequestProperty = new HttpRequestMessageProperty();
                httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = "Basic " +
                Convert.ToBase64String(Encoding.ASCII.GetBytes(UserName.Text + ":" + Password.Text));
                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;

                try
                {
                    response = client.sayHi("hi " + UserName.Text);
                }
                catch (TimeoutException tex)
                {
                    response = tex.Message;
                }
                catch (CommunicationException cex)
                {
                    response = cex.Message;
                }
            }

            TextBox.Text = response;

        }

我对其他需要基本身份验证的 Web 服务使用了相同的策略 在成功调用方法调用之前,但此服务似乎无法识别我的凭据。对于调用的每个方法调用,无论用户名/密码组合如何,我都会抛出 UnAuthorizedException。有人能给我一些启发吗?

提前致谢。

最佳答案

您的 shiro.ini 文件中需要有一个 [urls] 部分。像这样的事情:

[urls]
/** = authc

查看文档以了解更多详细信息 here .

关于web-services - 使用 INI 通过 Apache Shiro 保护 Apache CXF Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11368956/

相关文章:

java - 使用 Eureka 注册 Web 服务

java - 从 WSDL 文件创建客户端

java - UsernameToken 的 SOAP wsdl 规范

java - Apache CXF java2wsdl : Custom symbol names

java - Shiro Guice 权限解析器

java - Apache Shiro 的存储权限

java - 如何通过链接发送参数到java web服务以及如何在java中获取它

PHP NTLM身份验证+soap客户端

java - 表单的 CXF 方法声明

rest - 如何根据 HTTP 请求方法使用 Apache Shiro 进行基于角色的授权