自定义IDM身份验证和授权程序

时间:2014-07-21 07:48:13

标签: java authorization picketlink

我有Picketlink IDM JPA身份验证模型的自定义实现。我通过从https://github.com/jboss-developer/jboss-picketlink-quickstarts/tree/master/picketlink-idm-custom-identity-model处复制一个示例来打包org.picketlink.idm.jpa.model.custom.simple。然后我实现了这个例子https://github.com/pedroigor/picketlink-quickstarts/tree/master/picketlink-deltaspike-authorization。 我在picketlink-idm-custom-identity-model示例中更改了User class和UserTypeEntity,如下所示:

@IdentityStereotype(USER)
public class User extends AbstractIdentityType implements Account {
  public static final QueryParameter USER_NAME = QUERY_ATTRIBUTE.byName("userName");
  @StereotypeProperty(IDENTITY_USER_NAME)
  @AttributeProperty
  @Unique
  private String userName;
  @AttributeProperty
  private String firstName;
  @AttributeProperty
  private String lastName;
  @AttributeProperty
  private String email;
  @AttributeProperty
  private String middleName;
  @AttributeProperty
  private String telephone;
  @AttributeProperty
  private String address;
  @AttributeProperty
  private int postIndex;
  @AttributeProperty
  private Date registerDate;
  @AttributeProperty
  private Date lastVisitDate;
  @AttributeProperty
  private boolean isOrganizer;
  @AttributeProperty
  private boolean isAdmin;
  @Embedded
  private Organizer organizer;
  @Embedded
  private Customer customer;
  // getters and setters
}

class UserTypeEntity

  @IdentityManaged(User.class)
  @Entity
  public class UserTypeEntity extends AbstractIdentityTypeEntity {
  @AttributeValue
  private String userName;
  @OwnerReference
  @ManyToOne(fetch = FetchType.LAZY)
  private RealmTypeEntity realm;
  @AttributeProperty
  private String firstName;
  @AttributeProperty
  private String lastName;
  @AttributeProperty
  private String email;
  @AttributeProperty
  @Column(length = 255)
  private String middleName;
  @AttributeProperty
  @Size(max = 12)
  @Column(length = 12)
  private String telephone;
  @AttributeProperty
  @Column(length = 5000)
  @Size(max = 5000)
  private String address;
  @AttributeProperty
  private int postIndex;
  @AttributeProperty
  private Date registerDate;
  @AttributeProperty
  private Date lastVisitDate;
  @AttributeProperty
  private boolean isOrganizer;
  @AttributeProperty
  private boolean isAdmin;
  @Embedded
  private Organizer organizer;
  @Embedded
  private Customer customer;
  // getters and setters
}

然后我实现了Login controller:

@Named
@Stateless
public class LoginController {
  @Inject
  private Identity identity;
  @Inject
  private FacesContext facesContext;
  public void login() {
    AuthenticationResult result = identity.login();
    if (AuthenticationResult.FAILED.equals(result)) {
      facesContext.addMessage(
          null,
          new FacesMessage("Invalid user name or password"));
    }
  }
}

注册管理员:

@Named
@RequestScoped
public class RegistrationController {
  private IdentityManager identityManager;
  @Inject
  private PartitionManager partitionManager;
  @Inject
  private FacesContext facesContext;
  @Inject
  private User user;
  private String password;
  private String passwordVerify;
  private boolean isOrganizer;
  public RegistrationController() {
  }
  public User getUser() {
    return user;
  }
  public void setUser(User user) {
    this.user = user;
  }
  public String getPasswordVerify() {
    return passwordVerify;
  }
  public void setPasswordVerify(String passwordVerify) {
    this.passwordVerify = passwordVerify;
  }
  public boolean getIsOrganizer() {
    return isOrganizer;
  }
  public void setIsOrganizer(boolean isOrganizer) {
    this.isOrganizer = isOrganizer;
  }
  public String getPassword() {
    return password;
  }
  public void setPassword(String password) {
    this.password = password;
  }
  @Transactional
  public String register() throws Exception {
    if (password.isEmpty()) {
      String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "password.empty");
      facesContext.addMessage("signup:registrationPassword", new FacesMessage(message));
      return "returnToSignup";
    }
    if (!password.equals(passwordVerify)) {
      String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "password.NotEqual");
      facesContext.addMessage("signup:registrationPassword", new FacesMessage(message));
      return "returnToSignup";
    }
      identityManager = partitionManager.createIdentityManager(partitionManager.getPartition(Realm.class,
          Resources.REALM_ACME_NAME));
      if (isOrganizer) {
        user.setOrganizer(true);
        user.setOrganizer(new Organizer());
        try {
          identityManager.add(user);
        } catch (IdentityManagementException e) {
          String message = LocaleBean.loadErrorMessage(facesContext, LocaleBean.EX_RESOURCE_BUNDLE_NAME, "login.Registered");
          facesContext.addMessage(null, new FacesMessage(message));
          return "returnToSignup";
        }
        Password password = new Password(this.password);
        identityManager.updateCredential(user, password);
        RelationshipManager relationshipManager = partitionManager.createRelationshipManager();
        IdentityQuery<Group> query = identityManager.createIdentityQuery(Group.class);
        // query all childs of sales unit
        query.setParameter(Group.NAME, Resources.ORGANIZERS_GROUP_NAME);
        List<Group> groups = query.getResultList();
        Group organizersGroup = groups.get(0);
        relationshipManager.add(new GroupMembership(user, organizersGroup));
      } else {
      }
    return "signin";
  }
}

之后我实施了授权人:

@ApplicationScoped
public class SPAuthorizer {
  @Secures
  @Admins
  public boolean doAdminsCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
    return hasGroup(identity, identityManager, relationshipManager, Resources.ADMINS_GROUP_NAME);
  }
  @Secures
  @Organizers
  public boolean doOrganizersCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
    return hasGroup(identity, identityManager, relationshipManager, Resources.ORGANIZERS_GROUP_NAME);
  }
  @Secures
  @Customers
  public boolean doCustomersCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
    return hasGroup(identity, identityManager, relationshipManager, Resources.CUSTOMERS_GROUP_NAME);
  }
  private boolean hasGroup(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager,
                           String groupName) {
    IdentityQuery<Group> queryGroup = identityManager.createIdentityQuery(Group.class);
    // query all childs of sales unit
    queryGroup.setParameter(Group.NAME, groupName);
    List<Group> groups = queryGroup.getResultList();
    if (groups.size() == 1) {
      Group group = groups.get(0);
      Account user = identity.getAccount();
      if (user == null) {
        return false;
      }
      RelationshipQuery<GroupMembership> query = relationshipManager.createRelationshipQuery(GroupMembership.class);
      query.setParameter(GroupMembership.GROUP, group);
      query.setParameter(GroupMembership.MEMBER, user);
      // user is assigned with two groups
      List<GroupMembership> resultList = query.getResultList();
      return resultList.size() > 0;
    }
    return false;
  }
}

所以我实现了授权检查器来检查属于JSF中某个组的用户:

@Named
@Stateless
public class AuthorizationChecker {
  @Inject
  private Identity identity;
  @Inject
  private PartitionManager partitionManager;
  public boolean hasGroup(String groupName) {
    IdentityManager identityManager = partitionManager.createIdentityManager(partitionManager.getPartition(Realm.class,
        Resources.REALM_ACME_NAME));
    IdentityQuery<Group> queryGroup = identityManager.createIdentityQuery(Group.class);
    // query all childs of sales unit
    queryGroup.setParameter(Group.NAME, groupName);
    List<Group> groups = queryGroup.getResultList();
    if (groups.size() == 1) {
      Group group = groups.get(0);
      Account user = identity.getAccount();
      RelationshipManager relationshipManager = partitionManager.createRelationshipManager();
      RelationshipQuery<GroupMembership> query = relationshipManager.createRelationshipQuery(GroupMembership.class);
      query.setParameter(GroupMembership.GROUP, group);
      query.setParameter(GroupMembership.MEMBER, user);
      // user is assigned with two groups
      List<GroupMembership> resultList = query.getResultList();
      return resultList.size() > 0;
    }
    return false;
  }
}

但是SPAuthorizer的hasGroup中的Identity实例与AuthorizationChecker中的实例不对应。我在调试器中检查过它。当我执行identity.getAccount();时,虽然用户已经过身份验证,但它仍会返回null。知道该怎么办吗?

1 个答案:

答案 0 :(得分:1)

问题在于在Controller中错过了注释@Stateless。

有可行的示例https://github.com/lynx-r/picketlink-deltaspike-authorization-and-idm-custom-identity-model