Vaadin认证和授权

时间:2013-03-25 16:26:31

标签: vaadin jaas

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

我如何在Vaadin做到这一点?有最好的做法吗? 我正处于将某些东西放在一起的地步,但必须有某种标准程序,不应该! 我找到了一些关于此的教程,但主要是使用Spring(我想使用EJB)。 此外,每个教程似乎都不太复杂。

必须有一些简单的+结论性教程来解决这个问题。

3 个答案:

答案 0 :(得分:3)

以下是唯一一篇关于如何保护我能找到的Vaadin aplication using JAAS的Vaadin官方文章。我的意思是本土或官方的Vaadin证券化。如果你使用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和Password定义您喜欢的登录表单,并在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的替代方案

创建自定义登录模块不是必需的,通常作为Tomee的Java EE提供程序提供的实现很少。在某些数据库表中基于属性文件的身份验证。 请查看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 :(得分:1)

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

答案 2 :(得分:1)

使用JAAS,Vaadin 8,Vaadin CDI插件以及内置LoginForm的完整示例here,步骤如下:

  1. pom.xml
  2. 中启用Vaadin CDI加载项
  3. 使用@CDIUI注释启用CDI in Vaadin UI并配置Navigator
  4. 通过添加@RolesAllowed注释(或任何其他javax.annotation.security注释)启用authorization in a CDI view
  5. 实施从内置LoginForm派生的a login view,并使用JaasAccessControl对用户进行身份验证。
  6. 一旦你弄清楚这些碎片是如何组合在一起的,它实际上是一种相当不错,流畅的体验。

    Vaadin wiki中有一篇较长的文章解释了如何使用JAAS进行数据库支持的身份验证。