我试图在耳朵应用程序中使用apache shiro。我的想法是在ejb后端使用shiro,然后为战争前端提供服务,因为我希望在后端管理所有与权限相关的内容。
使用JpaRealm类进行身份验证:
public class JpaRealm extends AuthorizingRealm {
private static final Logger LOG = Logger.getLogger(JpaRealm.class.getName());
private static final String AUT_USUARIO_EJB = "java:global/Engine/Engine-ejb/AutUsuarioServices";
private AutUsuarioServices autUsuarioServices;
protected void lookup() {
try {
this.autUsuarioServices = (AutUsuarioServices) new InitialContext().lookup(AUT_USUARIO_EJB);
} catch (NamingException ex) {
LOG.log(Level.SEVERE, null, ex);
}
}
public JpaRealm() {
setName("JpaRealm");
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
try {
this.lookup();
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
AutUsuario usuario = autUsuarioServices.cargarUsuario(token.getUsername());
if (usuario != null) {
return new SimpleAuthenticationInfo(usuario.getIdUsuario(), usuario.getContrasena(), this.getName());
} else {
return null;
}
} catch (Exception ex) {
LOG.log(Level.SEVERE, null, ex);
return null;
}
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
try {
this.lookup();
Integer id = (Integer) principals.fromRealm(getName()).iterator().next();
AutUsuario usuario = autUsuarioServices.cargarUsuario(id);
if (usuario != null) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
for (AutRol rol : usuario.getAutRolCollection()) {
info.addRole(rol.getNombre());
ArrayList<String> permisos = new ArrayList<>();
for (AutPermiso permiso : rol.getAutPermisoCollection()) {
permisos.add(permiso.getPermiso());
}
info.addStringPermissions(permisos);
}
return info;
} else {
return null;
}
} catch (Exception ex) {
LOG.log(Level.SEVERE, null, ex);
return null;
}
}
}
AutUsuarioServices是一个@Stateless bean,它使用JPA加载和保存用户,因此没有任何谜。 在我的ejb中,我有一个ejb,在我的想法中,必须管理所有与用户相关的东西:
@Stateless
@LocalBean
public class UserServices implements UserServicesRemote {
private static final Logger LOG = Logger.getLogger(UserServices.class.getName());
private SecurityManager securityManager;
private String username;
@PostConstruct
public void init() {
LOG.log(Level.INFO, "*** UserServices:PostConstruct");
Factory<SecurityManager> factory = new IniSecurityManagerFactory("/opt/shiro.ini");
this.securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
}
@Override
public boolean login(String login, String contrasena) {
Subject subject = SecurityUtils.getSubject();
if (subject.isAuthenticated()) {
return true;
} else {
this.username = null;
UsernamePasswordToken token = new UsernamePasswordToken(login, contrasena);
token.setRememberMe(true);
try {
subject.login(token);
this.username = login;
return true;
} catch (Exception e) {
}
}
return false;
}
@Override
public String getUsuario() {
Subject subject = SecurityUtils.getSubject();
return "[" + subject.getPrincipal() + " " + subject.isAuthenticated() + "]" + this.username;
}
}
最后,在我的战争中,我有一个使用UserServices的UserBean,这个烘焙bean在登录页面和工作中使用:
@Named
@SessionScoped
public class UserBean implements Serializable {
private static final Logger LOG = Logger.getLogger(UserBean.class.getName());
private String loginFormUser;
private String loginFormPass;
@EJB
private UserServicesRemote userServices;
public String getLoginFormUser() {
return loginFormUser;
}
public void setLoginFormUser(String loginFormUser) {
this.loginFormUser = loginFormUser;
}
public String getLoginFormPass() {
return loginFormPass;
}
public void setLoginFormPass(String loginFormPass) {
this.loginFormPass = loginFormPass;
}
public String getUsername() {
return userServices.getUsuario();
}
public String login() {
LOG.log(Level.INFO,"*** login "+loginFormUser+" "+loginFormPass);
userServices.login(this.loginFormUser, this.loginFormPass);
// @TODO
return "ok";
}
}
当我调用登录方法时,它正常工作,使用jpa从数据库中调用用户数据等,并且我有一个正确登录的用户:后续调用UserServices.login告诉我用户已经登录。 无论如何,如果我将#{userBean.username}放在任何其他页面中,我总是得到null subject.getPrincipal()和false subject.isAuthenticated()。
我已经阅读了很多示例和文档,但我感到迷茫。我想知道我的方法是否正确......
我很欣赏有关在ejb后端使用shiro的示例的建议和指示。
谢谢