2013-03-25 93 views
5

我是Vaadin的新手。 在此之前,我制作了一个JSF Web应用程序。 我有一个ManagedBean执行用户的登录。我使用安全领域来委派实际的证书验证。Vaadin身份验证和Auhorization

我如何在Vaadin做到这一点?有最佳做法吗? 我在一个点上,我只是把一些东西放在一起,但必须有某种标准程序,不应该! 我发现了一些教程,但大多使用Spring(我想使用EJB)。另外,每个教程似乎并不复杂。

对于如此普遍的事情,必须有一些简单+确定的教程。

回答

3

这是唯一的Vaadin官方文章,关于如何保护我能找到的Vaadin aplication using JAAS。我的意思是本地或官方Vaadin Securization。如果你使用Spring安全性Shiro,你会发现更多,但纯粹的ESB使用JAAS。 我同意这篇文章不足以学习如何设置应用程序。我在这里分享我的经验:

1 Vaadin CDI扩展:

<!-- Vaadin Official DI support. --> 
<dependency> 
    <groupId>com.vaadin</groupId> 
    <artifactId>vaadin-cdi</artifactId> 
    <version>1.0.0.alpha2</version> 
</dependency> 

2.了解有关JAAS

我建议你去看看JAAS是如何工作在非vaadin应用程序,通过阅读概述文章,因为JAAS依赖于服务器应用程序提供者(TomEE,Jboss,Wildfly,Glasfish)都有不同的配置设置。 在这里您可以找到使用Tomee的proof of concept

3.开发自己的登录模块。

如果你决定创建例如自定义登录模块:

public class MyLoginModule implements LoginModule { 
private CallbackHandler handler; 
private Subject subject; 
private UserPrincipal userPrincipal; 
private RolePrincipal rolePrincipal; 
private String login; 
private List<String> userGroups; 
@Override 
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, 
Map<String, ?> options) { 
handler = callbackHandler; 
this.subject = subject; 
} 
@Override 
public boolean login() throws LoginException { 
Callback[] callbacks = new Callback[2]; 
callbacks[0] = new NameCallback("login"); 
callbacks[1] = new PasswordCallback("password", true); 
try { 
handler.handle(callbacks); 
String name = ((NameCallback) callbacks[0]).getName(); 
String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword()); 
// Here we validate the credentials against some 
// authentication/authorization provider. 
// It can be a Database, an external LDAP, a Web Service, etc. 
// For this tutorial we are just checking if user is "user123" and 
// password is "pass123" 
if (name != null && name.equals("admin") && password != null && password.equals("admin")) { 
login = name; 
userGroups = new ArrayList<String>(); 
userGroups.add("admin"); 
return true; 
} 
// If credentials are NOT OK we throw a LoginException 
throw new LoginException("Authentication failed"); 
} catch (IOException e) { 
throw new LoginException(e.getMessage()); 
} catch (UnsupportedCallbackException e) { 
throw new LoginException(e.getMessage()); 
} 
} 
@Override 
public boolean commit() throws LoginException { 
userPrincipal = new UserPrincipal(login); 
subject.getPrincipals().add(userPrincipal); 
if (userGroups != null && userGroups.size() > 0) { 
for (String groupName : userGroups) { 
rolePrincipal = new RolePrincipal(groupName); 
subject.getPrincipals().add(rolePrincipal); 
} 
} 
return true; 
} 
@Override 
public boolean abort() throws LoginException { 
return false; 
} 
@Override 
public boolean logout() throws LoginException { 
subject.getPrincipals().remove(userPrincipal); 
subject.getPrincipals().remove(rolePrincipal); 
return true; 
} 
} 

参考它在你的应用程序的META-INF/context.xml的。此设置适用于TomEE,但对于glashfish或其他必须类似。

<?xml version="1.0" encoding="UTF-8"?> 
<Context> 
    <Realm className="org.apache.catalina.realm.JAASRealm" appName="myrealm" userClassNames="net.sf.jaas.auth.UserPrincipal" 
    roleClassNames="net.sf.jaas.auth.RolePrincipal" /> 
</Context> 

注意userClassNames和roleClassNames只是简单的Java POJO的,但必须实现java.security.Principal中;

3.启用JAAS到您的Vaadin登录查看

定义自己喜欢的登录表单,使用Vaadin TextField和密码,并在您doLoginEvent定义()来JAAS一个引用。 每当调用JaasAccessControl.login时,都会创建一个LoginModule的新实例。

import com.vaadin.cdi.access.JaasAccessControl; 
    try { 
      JaasAccessControl.login(loginEvent.getUsername(), loginEvent.getPassword()); 
      logger.info("User {} authenticated", getPrincipalName()); 
      navigator.navigateTo(Main.NAME); 
     } catch (Exception e) { 
      Notification.show("Error logging in", Type.ERROR_MESSAGE); 
      logger.error(e.getMessage(), e); 
     } 

4.使用登录用户的信息。

每当用户通过JAAS登录过滤器时。在他的请求上下文中将提供一个能够识别他的类。这个类称为Principal(您之前在LoginModule类中设置的类)。

public boolean isUserInRole(String role) { 
     return JaasAccessControl.getCurrentRequest().isUserInRole(role); 
    } 

    public String getPrincipalName() { 
     Principal principal = JaasAccessControl.getCurrentRequest().getUserPrincipal(); 
     if (principal != null) { 
      return principal.getName(); 
     } 

     return null; 
    } 

    public boolean isUserSignedIn() { 
     Principal principal = JaasAccessControl.getCurrentRequest().getUserPrincipal(); 
     return principal != null; 
    } 

5.替代了LoginModule

这不是强制性的创建自定义登录模块,通常在Java EE提供商Tomee提供一些实现。基于属性文件的认证,在一些数据库表中。 对Tomee documentation JAAS一看就可以看一些例子:

6. TomEE 启用JAAS您需要创建它引用您的LoginModule一个的jaas.config文件,例如:

filename: jaas.config 
myrealm{ 
    net.sf.jaas.MyLoginModule required; 
}; 

然后启动具有此参数的应用程序服务器:

-Djava.security.auth.login.config=E:/apache-tomee-jaxrs-1.6.0.2/conf/jaas.config 

如果您想查看此概念的证明。 Checkout this example,它使用Tomee不同,Vaadin 7,JAAS,

1

几个月前我遇到了同样的问题。当时我无法弄清楚它是如何工作的,所以我去了春天的adddon,现在我正在使用Vaadin登录表单和弹簧安全

+0

非常感谢您的回答。不过,我会留下这个问题,因为有人可能会想出一个纯粹的Vaadin解决方案。 – fancy 2013-07-24 06:33:05

1

使用JAAS不同,Vaadin 8所述的完整的例子不同,Vaadin CDI附加和内置LoginForm可用here,步骤如下:

  1. 启用Vaadin CDI附加在pom.xml
  2. 启用CDI in Vaadin UI@CDIUI注释和配置Navigator
  3. 通过添加@RolesAllowed注释启用authorization in a CDI view(或任何其它javax.annotation.security注释)
  4. 执行a login view源自内置的LoginForm并使用JaasAccessControl来验证用户。

一旦你弄清楚这些零件如何组合在一起,它实际上是一个相当不错的流畅体验。

Vaadin wiki中有一篇较长的文章解释了如何在JAAS中使用数据库支持的认证。