如何在源代码

时间:2015-10-16 05:09:20

标签: java mysql database enums

在我们公司,我们讨论了如何在我们的java源代码中引用某些数据库条目。情况如下:

java web应用程序连接到由SQL脚本设置的MySQL数据库,JPA / Hibernate用于ORM。在这个脚本中,我们在"角色"中添加3个角色。表(即用户可以在Web应用程序中拥有的角色,即用户表具有角色表的外键)。角色具有预定义的主键/ ID(BIGINT)和名称(VARCHAR),如SQL脚本中所示。这些角色不用于安全框架,而是用于业务逻辑。目前它看起来像这样:

if(user.getRole.getId()==1) {
     // user is in role A
} else if(user.getRole().getId()==2) {
    // user is in role B
} ...

由于源代码必须在编译时知道角色(因为逻辑依赖于它们),我们必须检查用户是否具有某些角色。现在的问题是如何做到这一点。我们已经讨论过了:

a)更好地通过ID或名称进行检查 b)使用String / Long常量或Enums来检查相等性

到a)我更愿意检查ID(因为我们在数据库设置中使用脚本插入ID时不太可能改变),角色名称在应用程序的生命周期中更有可能被更改。 / p>

到b)我更喜欢使用常数,因为我不想依赖于Enums索引/序数。我们也不需要类型安全。我在枚举中看到的唯一优势是它很容易获取所有值,仅在常量的情况下才可以使用反射。但是,由于我们在DB上定义了所有角色,因此可以在运行时从那里获取它们。

有什么建议吗?

2 个答案:

答案 0 :(得分:4)

使用您的方法,在编译时需要角色,因此从数据库中获取它们无济于事。

我会使用存储id的枚举:

public enum Role {
     ROLE1(1), ROLE2(2), ROLE(3);

     private final int id;
     private Role(int id) {
         this.id=id;
     }

     public int getId() {
          return this.id;
     }
}

如果要将它们与数据库条目匹配(例如,要获取一些其他元数据),则已存储匹配的ID。这使您可以从数据库角色转换为枚举角色,反之亦然。

答案 1 :(得分:2)

我想告诉你@flo答案是对的。但是在这里我会给出另一种选择,我相信它对你的代码来说不是直截了当的,但也许这会引起你的兴趣。

@flo回答,非常适合您的问题,但您描述了角色的使用方式,您可以通过这种方式连接代码业务逻辑访问和角色,这可以通过不费力气来改进。

因此,您可以更灵活地使用不需要在将新角色添加到数据库时更改的类。

我的意思是:

public class Role {
    private Integer roleId = null;
    private String roleName = null;

    private static Map<Integer, String> roleMap = null;
    ...
}

您可以在应用程序开头,加载时,从数据库或使用某些属性文件或甚至使用Spring Bean填充roleMap(*在最后两种情况下,您需要修改此文件添加新角色或更改其名称)以将哪个ID分配给DB。

但最重要的问题是,如何以这种方式检查用户授权?

这可能会对您的代码造成一些破坏性影响,但考虑它可能需要一段时间。至少,有两种选择:

使用行动

显然,如果您不想在角色名称或角色ID上获得编译依赖关系,我建议您使用操作。操作可以是另一个连接表,用于将一组操作(字符串)与角色匹配。

Role

添加第二个静态地图
private Map<String, Set<String>> roleActionMap = null;

允许您实现以下方法

public boolean isAuthorized(String action, String role){
    boolean result = false;

    Set<String> actions = getActionSet(role);
    if(actions != null)
        result = actions.contains(action);

    return result;
}

您必须在bussines逻辑方法中连接操作以请求授权。一旦对代码重新排序,它就会变得更加清晰,即使不更改代码也可以更灵活地重新调整角色行为。

映射方法和角色

以非常类似的方式,您可以将角色与方法名称相关联,而不是创建关联角色和操作的映射,这样您就可以使用反射来检查方法是否被授权给角色。

因此,您可以检查用户授权,调用相同的上述方法,而是传递操作名称,传递

Thread.currentThread().getStackTrace()[1].getMethodName();

这将为您提供要从中检查授权的运行方法的名称。 (还有其他方法可以使用反射来获取方法名称,这可能更合适,具体取决于方案

最后,有更复杂和更好的框架,SpringSecurity是一个野兽,但如果你想要授权业务逻辑,而你不关心在视图逻辑和UI上使用授权,我认为我的两个选择很好。< / p>

希望它有所帮助。