我正在使用Picketlink( 2.6.0.Final )与JPA(使用Postgresql)进行持久化。我还实现了一个初始化程序,其基础如下:
@Singleton
@Startup
public class Initialiser {
@Inject
private PartitionManager partitionManager;
// Create users
@PostConstruct
public void createUsers()
{
try {
createUser("admin", new String[]{RoleConstants.BASIC});
} catch (Exception ex ) {} // Ignore error
try {
createUser("paul", new String[]{RoleConstants.BASIC, RoleConstants.IS_ADMIN});
} catch (Exception ex ) {} // Ignore error
}
private void createUser(String loginName, String[] roles)
{
User user = new User(loginName);
IdentityManager identityManager = this.partitionManager.createIdentityManager();
identityManager.add(user);
identityManager.updateCredential(user, new Password(loginName + "Test"));
for (String role: roles) {
Role xrole = new Role(role);
identityManager.add(xrole);
RelationshipManager relationshipManager = this.partitionManager.createRelationshipManager();
grantRole(relationshipManager, user, xrole);
}
}
}
将我的war
部署到Wildfly后,我确实看到我的用户是在配置的postgresql数据库中创建的 - 在accounttypeentity
表中。我可以使用普通的JPA方法(通过IdentityQuery
查找)查询和查找这些用户帐户。
问题:
我正在使用PL来保护我的Restful API(使用JAX-RS实现),他们这样做了吗?使用自定义注释来装饰每个端点,该注释旨在检查端点的调用者是否具有登录会话,以及关联用户帐户是否具有必要的角色(每个端点都将所需角色作为注释的一部分传递)。
现在,问题是,即使我有用户登录 - identity.isLoggedIn() == true
,即使此用户是我在初始化时创建的具有所需角色的用户之一,也要调用此用户是否有任何所需的角色都失败了!基本代码是:
hasRole(relationshipManager, user, getRole(identityManager, role)
整个自定义注释定义是:
@ApplicationScoped
public class CustomAuthorizer {
Logger log = Logger.getLogger(CustomAuthorizer.class);
@Inject
Identity identity;
@Inject
IdentityManager identityManager;
@Inject
RelationshipManager relationshipManager;
/**
* This method is used to check if classes and methods annotated with {@link BasicRolesAllowed} can perform
* the operation or not
*
* @param identity The Identity bean, representing the currently authenticated user
* @param identityManager The IdentityManager provides methods for checking a user's roles
* @return true if the user can execute the method or class
* @throws Exception
*/
@Secures
@BasicRolesAllowed
public boolean hasBasicRolesCheck(InvocationContext invocationContext) throws Exception {
log.error("** Checking roles...");
BasicRolesAllowed basicRolesAllowed = getAnnotation(invocationContext,BasicRolesAllowed.class);
String[] requiredRoles = basicRolesAllowed.value();// get these from annotation
Identity identity = getIdentity();
if((requiredRoles.length > 0) && (!getIdentity().isLoggedIn()))
{
log.error("** User Not Logged In: can't pass role checking...");
return false;
}
boolean isAuthorized = true;
User user = (User) getIdentity().getAccount();
for (String role : requiredRoles) {
isAuthorized = isAuthorized && hasRole(relationshipManager, user, getRole(identityManager, role));
log.info(String.format("User:%s | Role: %s | Has?: %s", user, role, isAuthorized));
}
return isAuthorized;
}
private <T extends Annotation> T getAnnotation(InvocationContext invocationContext, Class<T> annotationType) {
Class unproxiedClass = getUnproxiedClass(invocationContext.getTarget().getClass());
T annotation = (T) unproxiedClass.getAnnotation(annotationType);
Method invocationContextMethod = invocationContext.getMethod();
if (annotation == null) {
annotation = invocationContextMethod.getAnnotation(annotationType);
}
if (annotation == null) {
throw new IllegalArgumentException("No annotation [" + annotationType + " found in type [" + unproxiedClass + "] or method [" + invocationContextMethod + ".");
}
return annotation;
}
private Identity getIdentity() {
return this.identity;
}
}
所以,我会作弊并提出三个问题(一个):
答案 0 :(得分:1)
咨询了一位朋友。我实现了以下安全性注释实现,它按预期工作:
package com.dsmagic.satex.auth;
import com.dsmagic.satex.annotations.BasicRolesAllowed;
import org.apache.deltaspike.security.api.authorization.Secures;
import org.jboss.logging.Logger;
import org.picketlink.Identity;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.RelationshipManager;
import org.picketlink.idm.model.basic.BasicModel;
import org.picketlink.idm.model.basic.Role;
import org.picketlink.idm.model.basic.User;
import javax.enterprise.context.ApplicationScoped;
import javax.interceptor.InvocationContext;
@ApplicationScoped
public class Authorizer {
Logger log = Logger.getLogger(Authorizer.class);
@Secures
@BasicRolesAllowed
public boolean isBasicRolesAllowed(InvocationContext invocationContext, Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) {
boolean isUserAllowed = false;
if (identity != null && identity.isLoggedIn() && identity.getAccount() != null)
{
User user = BasicModel.getUser(identityManager, ((User)identity.getAccount()).getLoginName());
log.info(String.format("-------- Role-Checking for User: %s", user.getLoginName()));
if (invocationContext.getMethod().isAnnotationPresent(BasicRolesAllowed.class))
{
BasicRolesAllowed basicRolesAllowed = invocationContext.getMethod().getAnnotation(BasicRolesAllowed.class);
for (int i = 0; i < basicRolesAllowed.value().length; i++)
{
Role role = BasicModel.getRole(identityManager, basicRolesAllowed.value()[i]);
if (user != null && role != null)
{
if (BasicModel.hasRole(relationshipManager, user, role))
{
isUserAllowed = true;
break;
}else
log.info(String.format("-------- Doesn't have ROLE: %s", role.getName()));
}
}
}
}
return isUserAllowed;
}
}
希望这也有助于其他人。