2

在这里迫切需要帮助保护一个简单的 Apache CXF Web 服务。Spring Security 的尝试让我无处可去,所以我需要找到不同的策略。这是为了在为我们的一些客户实现的遗留 Java 服务上实现授权。

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

网页.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 标头中传递身份验证信息,如下所示:

 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。有人能给我一些启示吗?

提前致谢。

4

1 回答 1

2

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

[urls]
/** = authc

在此处查看文档以获取更多详细信息。

于 2012-07-06T21:16:24.970 回答