Cxf技巧之隐藏服务列表

最近接到的需求,要求隐藏服务请求列表清单,增加安全性。

1. 方法一:直接隐藏服务列表

经过翻阅相关资料和源码,最终发现CXF内置的支持——通过设置hide-service-list-page的Servlet初始化参数即可达到目的(该参数的读取和生效是在ServletController类中完成的)。

具体的配置方式如下(根据具体的环境任选其一):

  1. web.xml
<servlet>
	<servlet-name>CXFServlet</servlet-name>
	<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
	<init-param>
	    <!-- 隐藏服务列表 -->
		<param-name>hide-service-list-page</param-name>
		<param-value>true</param-value>
	</init-param>
</servlet>

<servlet-mapping>
	<servlet-name>CXFServlet</servlet-name>
	<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
  1. SpringBoot
# 直接在application.properties中配置如下键值对即可
cxf.servlet.init.hide-service-list-page=true
  1. Java代码(SpringBoot)
@Configuration
public class SelfConfigurer implements ServletContextInitializer {
	@Override
	public void onStartup(ServletContext servletContext) throws ServletException {
		// 		通过实现 ServletContextInitializer 接口直接注册Servlet
		//		因为我们需要设置 InitParameter, 所以不能直接使用ServletRegistrationBean
		final Dynamic servletDynamic = servletContext.addServlet("CXFServlet", CXFServlet.class);

		servletDynamic.addMapping("/ws/*");

		// 隐藏服务列表
		//servletDynamic.setInitParameter("hide-service-list-page", "true");
	}
}

2. 方法二:需要授权才能访问服务列表

在查找本文标题的解决方案时候,偶然在ServletController.init()的方法中发现了两个有趣的配置项service-list-page-authenticateservice-list-page-authenticate-realm。这里笔者就不多赘述其中的探究过程了,直接给出相应的配置项和实现步骤吧。

service-list-page-authenticate配置项的配置方法和上面的hide-service-list-page相同。这里需要一点注意的就只有service-list-page-authenticate-realm了。

service-list-page-authenticate-realm配置项

先看相关的配置文件

cxf.servlet.init.service-list-page-authenticate=true
cxf.servlet.init.service-list-page-authenticate-realm=fulizhe

所以这里的重点就成了fulizhe指代的内容。具体的原因参见下面的参考链接一,笔者这里只给出解决方案。毕竟能找到这里来的是为了解决问题的。

  1. 项目根目录创建名为fulizhe.config的文件,内容如下:
fulizhe {  
   com.xxx.yyy.zzz.configurer.FulizheLoginModule required debug=true;  
}; 
  1. 项目根目录创建名为fulizhe.policy的文件,内容如下:
grant  {  
    permission javax.security.auth.AuthPermission "createLoginContext.demo";  
    permission javax.security.auth.AuthPermission "modifyPrincipals";  
}; 
  1. 创建相关的Java类。
package com.xxx.yyy.zzz.configurer

public static class FulizheLoginModule implements LoginModule {
	private Subject subject;
	private CallbackHandler callbackHandler;
	private boolean success = false;
	private String user;
	private String pasword;

	@Override
	public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
			Map<String, ?> options) {
		this.subject = subject;
		this.callbackHandler = callbackHandler;
	}

	@Override
	public boolean login() throws LoginException {
		NameCallback nameCallback = new NameCallback("请输入用户名");
		PasswordCallback passwordCallback = new PasswordCallback("请输入密码", false);
		Callback[] callbacks = new Callback[] { nameCallback, passwordCallback };
		try {
			//执行回调,回调过程中获取用户名与密码  
			callbackHandler.handle(callbacks);
			//得到用户名与密码  
			user = nameCallback.getName();
			pasword = new String(passwordCallback.getPassword());
		} catch (IOException | UnsupportedCallbackException e) {
			success = false;
			throw new FailedLoginException("用户名或密码获取失败");
		}

		//为简单起见认证条件写死
		if ("fulizhe".equals(user) && "fulizhe".equals(pasword)) {
			success = true;//认证成功  
		}
		return true;
	}

	@Override
	public boolean commit() throws LoginException {
		if (!success) {
			return false;
		} else {
			//如果认证成功则得subject中添加一个Principal对象  
			//这样某身份用户就认证通过并登录了该应用,即表明了谁在执行该程序  
			this.subject.getPrincipals().add(new KanqPrincipal(user));
			return true;
		}
	}

	@Override
	public boolean abort() throws LoginException {
		logout();
		return true;
	}

	@Override
	public boolean logout() throws LoginException {
		//退出时将相应的Principal对象从subject中移除  
		Iterator<Principal> iter = subject.getPrincipals().iterator();
		while (iter.hasNext()) {
			Principal principal = iter.next();
			if (principal instanceof KanqPrincipal && principal.getName().equals(user)) {
				iter.remove();
				break;
			}
		}
		return true;
	}
}

public static class KanqPrincipal implements Principal {
	private String name;

	public KanqPrincipal(String name) {
		this.name = name;
	}

	@Override
	public String getName() {
		return this.name;
	}

}
  1. 在系统初始化完毕的事件回调位置注册系统属性
System.setProperty("java.security.auth.login.config", "fulizhe.config");
System.setProperty("java.security.policy", "fulizhe.policy");
  1. 启动应用,测试效果。

提示输入凭证
提示输入凭证

鉴权通过(用户名和密码都是 fulizhe)
鉴权通过

3. Links

  1. Java安全之认证与授权
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值