设为首页 收藏本站
查看: 1137|回复: 0

[经验分享] 自定义WebLogic Role Mapper Provider样例

[复制链接]
发表于 2017-2-17 08:14:11 | 显示全部楼层 |阅读模式
  【概述】
  开发环境:WebLogic Server 8.1
  本文仅记录了主要的操作流程,涉及到的一些概念性的东西,就不详细叙述。需要了解的话,可以参考其在线文档中心
  【Role Mapper Provider简介】
在请求者与Weblogic 资源之间建立动态关联(比如将用户所属的用户组与某个role进行映射)。当一个Weblogic资源被访问时,WebLogic Security Framework通过以下两种方式来确定哪个security roles将应用到某个特定的Subject上:
J2EEWebLogic部署描述符文件中获得security roles
使用业务逻辑和当前操作参数来决定security roles
  在一个security realm中,至少需要有一个Role Mapping Provider。
  【开发流程】
      首先,需要一个weblogic.security.service.SecurityRole的实现类:
  
package examples.security.providers.rolemapper;
import weblogic.security.service.SecurityRole;
public class SampleSecurityRoleImpl implements SecurityRole {
private String _roleName;
private String _description;
private int _hashCode;
public SampleSecurityRoleImpl(String roleName, String description) {
_roleName = roleName;
_description = description;
_hashCode = roleName.hashCode() + 17;
}
public boolean equals(Object secRole) {
if (secRole == null) {
return false;
}
if (this == secRole) {
return true;
}
if (!(secRole instanceof SampleSecurityRoleImpl)) {
return false;
}
SampleSecurityRoleImpl anotherSecRole = (SampleSecurityRoleImpl) secRole;
if (!_roleName.equals(anotherSecRole.getName())) {
return false;
}
return true;
}
public String toString() {
return _roleName;
}
public int hashCode() {
return _hashCode;
}
public String getName() {
return _roleName;
}
public String getDescription() {
return _description;
}
}
  

  实现代码很简单,一个role基本上就包含名称和描述。
  然后,为了简化起见,这里用一个类SampleRoleMapperDatabase来代替数据库里面存储的相关映射信息。实际应用中,可以改造这个类,让它读写数据库或其他存储设备。



package examples.security.providers.rolemapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import weblogic.management.security.ProviderMBean;
import weblogic.security.spi.Resource;
public class SampleRoleMapperDatabase {
private Map roleMap = new Hashtable();
private Map principalMap = new Hashtable();
public SampleRoleMapperDatabase(ProviderMBean mbean) {
}
public void setRole(Resource resource, String roleName,
String[] principalNames) {
Vector principalVector = (Vector) principalMap.get(roleName);
if (principalVector == null) {
principalVector = new Vector();
principalMap.put(roleName, principalVector);
}
principalVector.addAll(Arrays.asList(principalNames));
Vector roleVector = (Vector) roleMap.get(resource);
if (roleVector == null) {
roleVector = new Vector();
roleMap.put(resource, roleVector);
}
roleVector.add(roleName);
}
public void removeRole(Resource resource, String roleName) {
if (resource != null)
principalMap.remove(roleName);
if (roleName != null)
roleMap.remove(resource);
}
public Enumeration getRoles(Resource resource) {
if (resource == null)
return null;
if (roleMap.get(resource) != null)
return Collections.enumeration((Vector) roleMap.get(resource));
else
return null;
}
public Enumeration getPrincipalsForRole(Resource resource, String role) {
List pricipalList = new ArrayList();
if (role != null)
pricipalList.addAll((Vector) roleMap.get(role));
if (resource != null) {
Vector roleVector = (Vector) roleMap.get(resource);
if (roleVector != null) {
Iterator iter = roleVector.iterator();
while (iter.hasNext()) {
Vector principalVector = (Vector) principalMap
.get((String) iter.next());
pricipalList.addAll(principalVector);
}
}
}
return Collections.enumeration(pricipalList);
}
}

  接下来,就可以开始实现weblogic.security.spi.RoleMapper接口了。该接口只有一个方法:

public Map getRoles(Subject subject, Resource resource,
ContextHandler handler)
  给定一个登录用户的Subject,和其请求的资源,返回在该资源上分配给该用户的所有role,返回的对象是一个Map,key是对应role的名称,value则是weblogic.security.service.SecurityRole对象(也就是上文中我们自己写的那个实现类)。
  另外,我们还可以同时实现weblogic.security.spi.DeployableRoleProvider接口,这样如果在web.xml中配置了某些角色,那么在服务器启动时,WebLogic Server会将这些信息注入到我们的这个实现类里面去。该接口有两个方法:

public void deployRole(Resource resource, String roleName,
String[] principalNames) throws RoleCreationException;
public void undeployRole(Resource resource, String roleName)
throws RoleRemovalException;
  分别对应添加和删除映射关系,我们根据传入的参数,修改数据库或其他地方的持久化映射数据。
  完整实现类代码如下:

package examples.security.providers.rolemapper;
import java.security.Principal;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.security.auth.Subject;
import weblogic.management.security.ProviderMBean;
import weblogic.security.WLSPrincipals;
import weblogic.security.service.ContextHandler;
import weblogic.security.spi.DeployableRoleProvider;
import weblogic.security.spi.Resource;
import weblogic.security.spi.RoleCreationException;
import weblogic.security.spi.RoleMapper;
import weblogic.security.spi.RoleRemovalException;
import weblogic.security.spi.SecurityServices;
public final class SampleRoleMapperProviderImpl implements
DeployableRoleProvider, RoleMapper {
private String description;
private SampleRoleMapperDatabase database;
private static final Map NO_ROLES = Collections
.unmodifiableMap(new HashMap(1));
public void initialize(ProviderMBean mbean, SecurityServices services) {
SampleRoleMapperMBean myMBean = (SampleRoleMapperMBean) mbean;
description = myMBean.getDescription() + "\n" + myMBean.getVersion();
database = new SampleRoleMapperDatabase(mbean);
}
public String getDescription() {
return description;
}
public void shutdown() {
System.out.println("SampleRoleMapperProviderImpl.shutdown");
}
public RoleMapper getRoleMapper() {
return this;
}
public Map getRoles(Subject subject, Resource resource,
ContextHandler handler) {
System.out.println("SampleRoleMapperProviderImpl.getRoles");
System.out.println("\tsubject\t= " + subject);
System.out.println("\tresource\t= " + resource);
Map roles = new HashMap();
Set principals = subject.getPrincipals();
for (Resource res = resource; res != null; res = res
.getParentResource()) {
getRoles(res, principals, roles);
}
getRoles(null, principals, roles);
if (roles.isEmpty()) {
return NO_ROLES;
}
return roles;
}
public void deployRole(Resource resource, String roleName,
String[] principalNames) throws RoleCreationException {
System.out.println("SampleRoleMapperProviderImpl.deployRole");
System.out.println("\tresource\t\t= " + resource);
System.out.println("\troleName\t\t= " + roleName);
for (int i = 0; principalNames != null && i < principalNames.length; i++) {
System.out.println("\tprincipalNames[" + i + "]\t= "
+ principalNames);
}
database.setRole(resource, roleName, principalNames);
}
public void undeployRole(Resource resource, String roleName)
throws RoleRemovalException {
System.out.println("SampleRoleMapperProviderImpl.undeployRole");
System.out.println("\tresource\t= " + resource);
System.out.println("\troleName\t= " + roleName);
database.removeRole(resource, roleName);
}
private void getRoles(Resource resource, Set principals, Map roles) {
for (Enumeration e = database.getRoles(resource); e != null
&& e.hasMoreElements();) {
String role = (String) e.nextElement();
if (roleMatches(resource, role, principals)) {
roles.put(role, new SampleSecurityRoleImpl(role,
"no description"));
}
}
}
private boolean roleMatches(Resource resource, String role,
Set principalsHave) {
for (Enumeration e = database.getPrincipalsForRole(resource, role); e
.hasMoreElements();) {
String principalWant = (String) e.nextElement();
if (principalMatches(principalWant, principalsHave)) {
return true;
}
}
return false;
}
private boolean principalMatches(String principalWant, Set principalsHave) {
if (WLSPrincipals.getEveryoneGroupname().equals(principalWant)
|| (WLSPrincipals.getUsersGroupname().equals(principalWant) && !principalsHave
.isEmpty())
|| (WLSPrincipals.getAnonymousUsername().equals(principalWant) && principalsHave
.isEmpty())
|| principalsContain(principalsHave, principalWant)) {
return true;
}
return false;
}
private boolean principalsContain(Set principalsHave,
String principalNameWant) {
for (Iterator i = principalsHave.iterator(); i.hasNext();) {
Principal principal = (Principal) i.next();
String principalNameHave = principal.getName();
if (principalNameWant.equals(principalNameHave)) {
return true;
}
}
return false;
}
}

  initialize()方法在WebLogic Server启动时会被自动调用,在这里我们可以根据需要进行一些初始化操作。
  代码写完了,接下来,就要使用WebLogic提供的命令行工具来生成一个mbi文件,这个文件在后面往WebLogic Server里面部署我们的Provider时需要用到。
  为了告诉WebLogic如何生成我们的这个mbi文件,我们需要编写一个xml文档。
  SampleRoleMapper.xml内容如下:

<?xml version="1.0" ?>
<!DOCTYPE MBeanType SYSTEM "commo.dtd">
<MBeanType
Name="SampleRoleMapper"
DisplayName="自定义RoleMapper"
Package="examples.security.providers.rolemapper"
Extends="weblogic.management.security.authorization.DeployableRoleMapper"
PersistPolicy="OnUpdate"
Description="This MBean represents configuration attributes for the Sample RoleMapper Provider.&lt;p&gt;"
>
<MBeanAttribute
Name="ProviderClassName"
Type="java.lang.String"
Writeable="false"
Default="&quot;examples.security.providers.rolemapper.SampleRoleMapperProviderImpl&quot;"
Description="The name of the Java class that my first role mapper provider." />
<MBeanAttribute
Name="Description"
Type="java.lang.String"
Writeable="false"
Default="&quot;Provider that performs role mapper&quot;"
Description="None." />
<MBeanAttribute
Name="Version"
Type="java.lang.String"
Writeable="false"
Default="&quot;1.0&quot;"
Description="The version of the Sample Role Mapper Provider." />
</MBeanType>
  MBeanType标签的Name属性,跟后面自动生成的java文件名有关,这里不可以命名成跟上文中我们自己写的Provider实现类同名;DisplayName随便写;Package跟上文相关类的包名保持一致即可;Extends属性比较关键,根据WebLogic Server的API来,只不过API里面的类名结尾有个MBean,这边去掉这个后缀即可。
  三个MBeanAttribute标签的Name是固定的,直接拷贝。当然Name为ProviderClassName的这个MBeanAttribute要修改一下Default属性,改为我们自己的那个Provider实现类的全类名,注意要用转义的双引号(&quot;)括起来。
  比较关键的修改就这些,其他属性看着改就好了。特别需要强调的是,这个xml文件比较关键,稍微错一点,后面代码生成就会出错。
  编写完这个xml文件(MBeanType定义文件)后,还需要拷贝一个commo.dtd文件到相同目录,这个文件在C:\bea\weblogic81\server\lib目录可以找到。
  运行cmd命令,打开命令行窗口。先运行:C:\bea\weblogic81\server\bin\setWLSEnv.cmd进行环境变量设置。
  然后运行以下命令,生成mbi文件:
  java -DMDF=C:\bea\user_projects\applications\Test3\Test3Web\WEB-INF\src\examples\security\providers\rolemapper\SampleRoleMapper.xml -Dfiles=D:\temp\0209 -DcreateStubs=true -cp .;%CLASS_PATH%;C:\bea\weblogic81\server\lib\weblogic.jar;C:\bea\weblogic81\server\lib\mbeantypes\wlManagement.jar;C:\bea\jdk142_08\lib\tools.jar weblogic.management.commo.WebLogicMBeanMaker
  其中-DMDF参数指定SampleRoleMapper.xml文件位置;-Dfiles参数指定要生成的文件存放位置,这里我指定了一个临时目录;注意需要将weblogic.jar、wlManagement.jar和对应jdk的tools.jar文件在classpath中明确指定。
  如果一切顺利的话,WebLogicMBeanMaker工具将生成两个java文件和一个mbi文件。如果上述SampleRoleMapper.xml文件中稍有错误(比如少了一个&quot;),过程中就会提示编译错误,其实是该工具根据我们编写的xml自动生成的java文件出现编译错误。此时应该仔细检查xml文件,甚至需要重新编写一次该文件(有一次我就遇到怎么查也没错,把文件删了重写一遍就好了)。
  文件生成完了之后,接下来就是打包发布了。WebLogic也有提供相应工具,不过我还是自己用ant做比较方便。把两个java文件拷贝到eclipse里面,跟自己写的那三个文件放一起。另外再找个目录放生成的mbi文件。
  然后编写一个ant脚本来打包发布jar文件,方便后续修改代码进行调试。

<?xml version="1.0" encoding="UTF-8"?>
<project name="Test3" default="自定义授权Provider">
<property name="classBase" value="${basedir}/Test3Web/WEB-INF/classes"/>
<property name="mbiBase" value="${classBase}/examples/security/providers/mbi"/>
<property name="mbeantypesBase" value="C:/bea/weblogic81/server/lib/mbeantypes"/>
<description>
WebLogic Security Provider 自动打包发布
</description>
<target name="自定义RoleMapperProvider">
<jar destfile="${mbeantypesBase}/myRoleMapperProvider.jar">
<fileset
dir="${classBase}"
includes="examples/security/providers/rolemapper/,examples/util/"/>
<fileset file="${mbiBase}/SampleRoleMapper.mbi"/>
</jar>
</target>
</project>

  这里我们把用到的class文件和mbi文件打包后,直接拷贝到C:/bea/weblogic81/server/lib/mbeantypes目录中去,这样就完成了部署操作。
  接下来,启动WebLogic服务器,打开浏览器,进入http://localhost:7001/console控制台页面,登录后就能看到我们自己的这个provider了。
  配置完了以后,重启WebLogic服务器,即可生效。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-343157-1-1.html 上篇帖子: 忘记Weblogic,如何修改密码(10.3.2.0测试通过) 下篇帖子: org.hibernate.hql.ast.HqlToken 错误weblogic异常
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表