JPA - 使用多个数据源来定义访问控制 [英] JPA - Using Multiple data sources to define access control

查看:144
本文介绍了JPA - 使用多个数据源来定义访问控制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对JPA和JSF完全陌生,希望你能帮我解决我的问题。
我的应用程序是使用JSF 2.0 Framework构建的,使用在Glassfish 3+,MySQL上运行的JPA 2.0 / EclipseLink。我设置了一个名为loginPU的持久性单元,使用数据源:jdbc / loginDataSource
jdbc / loginDataSource使用login1连接到MySQL(定义在 mysql user 表),并且只能访问客户用户

我创建了2个其他数据在Glassfish JDBC资源中使用源代码jdbc / admin和jdbc / staff,并且具有不同的权限



登录/身份验证方案为:


  1. 使用基于表单的身份验证(用户名和密码)进行用户登录

  2. 使用持久性单元loginPU和jdbc / loginDataSource创建EntityManageFactory

  3. 创建查询以检索用户角色如果用户角色是admin,则使用jdbc / admin数据源连接
  4. / li>
  5. 如果用户角色是人员,则使用jdbc / staff数据源连接

我的代码对于上面的项目2看起来像这样:

  Map properties = new HashMap(); 
properties.put(TRANSACTION_TYPE,JTA);

//配置内部EclipseLink连接池
properties.put(JDBC_DRIVER,com.mysql.jdbc.Driver);
properties.put(JDBC_URL,jdbc:mysql:// localhost:3306 / customer);
properties.put(JDBC_USER,login1);
properties.put(JDBC_PASSWORD,login1);
properties.put(JTA_DATASOURCE,jdbc / loginDataSource);

EntityManageFactory emf = Persistence.createEntityManagerFactory(loginPU,properties);

我甚至会将我的EntityManagerFactory保留在会话属性中,并在JpaController类中检索它

  //保存到会话
session.setAttribute(entityManagerFactory,emf);

//在JpaController中检索
public EntityManagerFactory getEmf(){
$ b $ HttpServletRequest request =(HttpServletRequest)FacesContext.getCurrentInstance()。getExternalContext()。getRequest() ;
HttpSession s = request.getSession(true);
尝试{
emf =(EntityManagerFactory)s.getAttribute(entityManagerFactory);
} catch(NullPointerException ne){
System.out.println(EMF Exception:+ ne);
}

返回emf;
}




问题:我怎样才能达到4或5号?这可能是
吗?是否可以将数据源分配给loginPU
持久性单元?我设法使用loginPU和jdbc / loginDataSource
建立连接,然后使用jdbc / admin数据源进行连接,但是当我访问其他
实体时,它会将错误和缺省值引发至jdbc / loginDataSource


注意:
我使用由netbeans创建的JpaController类,也使用会话bean来管理实体。
我的JpaController类使用

  @Resource private UserTransaction utx; 
@PersistenceUnit private EntityManagerFactory emf;

我的会话bean都是@Stateless,我试图使用@PersistenceContext和unitName,但没有unitName,但没有好运

  @PersistenceContext 
私人EntityManager em;

我尝试在persistence.xml中使用多个持久性单元,希望能够使用基于持久性单元名称的用户在角色上,但是当部署到服务器时,它给了我错误。



我阅读了关于应用程序管理的持久性 container-managed ,我想我试图实现的是使用应用程序管理,但不知道如何去做。



如果我要使用容器管理的持久性,是否可以使用多个数据源?任何建议,不胜感激。



感谢您提前发表任何意见或建议。

[已解决]


  1. 首先我定义了我的persistence.xml,如下所示:

     < persistence version =2.0xmlns =http://java.sun.com/xml/ns/persistencexmlns:xsi =http:/ /www.w3.org/2001/XMLSchema-instancexsi:schemaLocation =http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0的.xsd> 
    < persistence-unit name =mdbAdminPU>
    < provider> org.eclipse.persistence.jpa.PersistenceProvider< / provider>
    < jta-data-source> jdbc / login< / jta-data-source>
    < exclude-unlisted-classes> false< / exclude-unlisted-classes>
    < / persistence-unit>
    < /余辉>


  2. 在会话bean中不使用任何@PersistenceUnit或@PersistenceContext。使用Netbeans创建JSF页面时创建了这些bean)



  3.   @Stateless 
    public class UserFacade extends AbstractFacade< User> {

    @Override
    protected EntityManager getEntityManager(){
    HttpSession session =(HttpSession)FacesContext.getCurrentInstance()。getExternalContext()。getSession(false);
    EntityManagerFactory emf =(EntityManagerFactory)session.getAttribute(entityManagerFactory);
    EntityManager em = emf.createEntityManager();
    返回em;
    }

    public UserFacade(){
    super(User.class);


    $ / code $
  4. 上面的登录方案(5个项目)已成为7:





  1. 使用基于表单的用户登录认证(用户名和密码)
  2. 使用持久性单元loginPU和jdbc / loginDataSource创建EntityManageFactory
  3. 创建查询以检索用户角色
  4. li>
  5. 如果用户角色是admin,使用jdbc / admin数据源连接
  6. 如果用户角色是staff,则使用jdbc / staff数据源连接


加上



  1. 使用
    删除或清除在项目2中创建的EntityManagerFactory emf.close();

  2. 保留在项目4中创建的新EntityManagerFactory或5 in
    HttpSession



解决方案

可能最好在Persis中使用三个单独的持久性单元tence.xml,如果你需要三个不同的登录。或者只是一个拥有完全访问权限的单一登录并验证应用程序中的安全性(无论如何你似乎都在这样做)。



部署时出现什么错误?

您可以在EclipseLink中使用一个持久性单元来执行此操作,但涉及更多,并且您无法使用容器管理实体管理器。你会注入@PersistenceUnit(EntityManagerFactory)而不是@PersistenceContext(EntityManager),那么你需要将新的登录参数传递给createEntityManager()。您需要将eclipselink.jdbc.exclusive-connection.mode属性设置为始终(或隔离并隔离安全数据)。

请参阅
http://wiki.eclipse.org/EclipseLink/Examples/JPA /审核


I am totally new to JPA and JSF and hope you can help me with my questions. My application is built using JSF 2.0 Framework, using JPA 2.0/EclipseLink running on Glassfish 3+, MySQL.

I set one persistence unit called "loginPU" using data source: "jdbc/loginDataSource" "jdbc/loginDataSource" connects to MySQL using "login1" (defined in mysql.user table) and only has access to customer.user and customer.roles tables, with only select privileges.

I created 2 other data sources "jdbc/admin" and "jdbc/staff" in Glassfish JDBC Resources and both with different privileges

The login/authentication scenario is:

  1. User login using form based authentication (username and password)
  2. Create EntityManageFactory using persistence unit "loginPU" and "jdbc/loginDataSource"
  3. create query to retrieve user role
  4. if user role is admin, connect using "jdbc/admin" data source
  5. if user role is staff, connect using "jdbc/staff" data source

My code for item 2 above looks like this:

Map properties = new HashMap(); 
properties.put(TRANSACTION_TYPE, "JTA");

// Configure the internal EclipseLink connection pool
properties.put(JDBC_DRIVER, "com.mysql.jdbc.Driver");
properties.put(JDBC_URL, "jdbc:mysql://localhost:3306/customer");
properties.put(JDBC_USER, "login1");
properties.put(JDBC_PASSWORD, "login1");
properties.put(JTA_DATASOURCE, "jdbc/loginDataSource");

EntityManageFactory emf = Persistence.createEntityManagerFactory("loginPU",properties);

I even keep my EntityManagerFactory in session attributes and retrieve it in the JpaController class

//save into session
session.setAttribute("entityManagerFactory", emf);

//retrieved in JpaController
public EntityManagerFactory getEmf() {

        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        HttpSession s = request.getSession(true);
        try {
            emf = (EntityManagerFactory) s.getAttribute("entityManagerFactory");
        } catch(NullPointerException ne){
            System.out.println("EMF Exception: "+ne);
        }

        return emf;
    }

Questions: How can I achieve number 4 or number 5? Is that possible to do? Is it possible to assign either data source to "loginPU" persistence unit? I manage to establish connection using loginPU and jdbc/loginDataSource and then connect using jdbc/admin datasource, but when I access other entities, it throws error and default to jdbc/loginDataSource

Note: I am using JpaController classes created by netbeans, and also session beans to manage the entities. My JpaController classes use

@Resource private UserTransaction utx;
@PersistenceUnit private EntityManagerFactory emf;

My session beans are all @Stateless, I tried to use @PersistenceContext with unitName and without unitName but no luck

@PersistenceContext
private EntityManager em;

I tried using multiple persistence units in persistence.xml, hoping to connect users using the persistence unit name based on the role, but it gives me error when deploying to server.

I read about application-managed persistence and container-managed, I think what I am trying to achieve is to use application-managed, but not sure how to do it.

If I am to use container-managed persistence, is it possible to use multiple data sources? Any suggestion is greatly appreciated.

Thank you for any comments or suggestions in advance.

[SOLVED]

  1. First I defined my persistence.xml as follows:

    <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="mdbAdminPU" >
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <jta-data-source>jdbc/login</jta-data-source>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
        </persistence-unit>
    </persistence>
    

  2. I don't use any @PersistenceUnit or @PersistenceContext in my session beans.(I'm using Netbeans and these beans were created when I created JSF Pages from Entity Classes)

  3. In all session beans, they look like this:

    @Stateless
    public class UserFacade extends AbstractFacade<User> {
    
        @Override
        protected EntityManager getEntityManager() {
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            EntityManagerFactory emf = (EntityManagerFactory) session.getAttribute("entityManagerFactory");
            EntityManager em = emf.createEntityManager(); 
            return em;
        }
    
        public UserFacade() {
            super(User.class);
        }
    }
    

  4. The login scenario above (5 items) has become 7:

  1. User login using form based authentication (username and password)
  2. Create EntityManageFactory using persistence unit "loginPU" and "jdbc/loginDataSource"
  3. create query to retrieve user role
  4. if user role is admin, connect using "jdbc/admin" data source
  5. if user role is staff, connect using "jdbc/staff" data source

plus

  1. remove or clear EntityManagerFactory created in item 2 using emf.close();
  2. Keep new EntityManagerFactory created in either item 4 or 5 in HttpSession

解决方案

You are probably best off using three separate persistence units in your persistence.xml if you need three different logins. Or just have a single login with full access and validate security in your application (which you seem to be doing in part anyway).

What error did you get on deploy?

You can do it with one persistence unit in EclipseLink but it is more involved, and you cannot use container managed entity managers. You would inject a @PersistenceUnit (EntityManagerFactory) instead of an @PersistenceContext (EntityManager), then you would need to pass the new login parameters to createEntityManager(). You would need to set the "eclipselink.jdbc.exclusive-connection.mode" property to "Always" (or "Isolated" and make the secure data isolated).

See, http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing

这篇关于JPA - 使用多个数据源来定义访问控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆