シンプルな Apache CXF Web サービスを保護するには、ここで助けが必要です。Spring Security を試してもどこにも行かないので、別の戦略を見つける必要があります。これは、一部のクライアント向けに実装されたレガシー Java サービスに承認を実装するためのものです。
この単純な Apache CXF Web サービスは、Maven の cxf-jaxws-javafirst プロトタイプを使用して作成されました。これにより、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
私の単純な Web サービス コードは次のとおりです。
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);
}
}
次のように、Web サービスを呼び出す前に SOAP ヘッダーで認証情報を渡す C# テスト クライアントがあります。
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 がスローされます。誰かが私に光を当てることができますか?
前もって感謝します。