Docs

Documentation versions (currently viewingVaadin 24)
Documentation translations (currently viewingChinese)

此页面是从官方文档(http://vaadin.com/docs)机器翻译而来。可能包含错误、不准确或误解的表述。Vaadin 不保证翻译的准确性、可靠性或及时性。

配置Servlet容器身份验证

Configuring session-based and servlet container authentication.

当需要对受保护端点进行身份验证时,不同的Servlet容器具有不同的机制用来创建用户[classname]`Principal`对象并执行安全检查。

作为参考,本页面提供了两种流行容器中基于自定义会话的认证配置示例。

基于会话的身份验证

配置自定义Servlet过滤器

要实现自定义认证,需编写一个自定义的[classname]`HttpServletRequest`实现,使用[classname]`WebFilter`对默认身份验证进行包装。

以下示例展示了一种自定义[classname]`Principal`对象实现。 假设应用程序已在某个时刻将此Principal对象设置为[classname]`Session`的属性。

Source code
CustomPrincipal.java
public class CustomPrincipal implements Principal {
    private final String name;
    private final List<String> roles;

    public CustomPrincipal(String name, String ...roles) {
        this.name = name;
        this.roles = Arrays.asList(roles);
    }

    public String getName() {
        return name;
    }

    public boolean isUserInRole(String role) {
        return roles.contains(role);
    }
}
Source code
CustomHttpServletRequest.java
public class CustomHttpServletRequest extends HttpServletRequestWrapper {
    public CustomHttpServletRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public Principal getUserPrincipal() {
        Principal myUser = (Principal) getSession().getAttribute("User");
        return myUser != null ? myUser : super.getUserPrincipal();
    }

    @Override
    public boolean isUserInRole(String role) {
        return getUserPrincipal() instanceof CustomPrincipal
                && ((CustomPrincipal) getUserPrincipal()).isUserInRole(role)
                || super.isUserInRole(role);
    }
}
Source code
CustomWebFilter.java
@WebFilter("/connect")
public class CustomWebFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        chain.doFilter(new CustomHttpServletRequest((HttpServletRequest) request), response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }

    @Override
    public void destroy() { }
}

配置客户端登录表单

创建一个表单,用于向用户请求用户名与密码,并将其发送到服务器端。 以下代码段展示了如何实现一个登录web组件。

Source code
frontend/my-login.ts
import { html, LitElement } from 'lit';
import { customElement, query } from 'lit/decorators.js';

@customElement("my-login")
export class MyLogin extends LitElement {
  @query('#username')
  private username: any;
  @query('#password')
  private password: any;

  render() {
    return html`
      <input id="username" name="username" />
      <input id="password" name="password" type="password" />
      <button @click="${this.login}">login</button>
    `;
  }

  private login() {
    fetch('/connect/login', {
      method: 'POST',
      body: `username=${this.username.value}&password=${this.password.value}`
    })
    .then(() => console.log("User Logged-in"));
  }
}

接下来,修改上面的过滤器以处理请求,并在会话中设置合适的Principal对象。

Source code
CustomWebFilter.java
@WebFilter("/connect")
public class CustomWebFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        // 检查用户名/密码并在Session中设置`User`属性
        if ("foo".equals(request.getParameter("username")) &&
            "abc123".equals(request.getParameter("password"))) {
            ((HttpServletRequest) request).getSession()
                .setAttribute("User", new CustomPrincipal("foo"));
        }

        // 用我们的定制实现包装原始请求
        chain.doFilter(new CustomHttpServletRequest((HttpServletRequest) request), response);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException { }
    @Override
    public void destroy() { }
}

配置Servlet容器身份验证

以下各节展示如何配置Jetty和Tomcat服务器,使用Basic HTTP authentication方案实施身份验证。

Note
Basic HTTP authentication被认为是不安全的。 对于公共以及生产环境部署,建议使用基于表单的认证或客户端证书认证。 大多数Servlet容器都可以配置支持这些认证方式。

配置Jetty

Source code
$JETTY_HOME/etc/jetty-users.properties
test: password1,user
admin: password2,user,admin
Source code
$JETTY_HOME/etc/jetty.xml
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/connect</Set>
  <Set name="war"><SystemProperty name="jetty.home" default="."/>/webapps/my-app</Set>

  <Get name="securityHandler">
    <Set name="loginService">
      <New class="org.eclipse.jetty.security.HashLoginService">
        <Set name="name">my-app</Set>
        <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/jetty-users.properties</Set>
      </New>
    </Set>
  </Get>
</Configure>
Note
'realm’是存储用户信息的仓库。 `HashLoginService`是一种从Java properties文件加载用户名的登录服务,而`JDBCLoginService`可以从JDBC数据源读取用户信息。

配置Tomcat

Source code
$CATALINA_HOME/conf/tomcat-users.xml
<tomcat-users>
  <role rolename="admin" />
  <role rolename="user" />
  <user name="test" password="password1" roles="user" />
  <user name="admin" password="password2" roles="user,admin" />
</tomcat-users>
Source code
$CATALINA_HOME/conf/server.xml
<Context path="/connect">
  <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
         resourceName="UserDatabase" />
</Context>
Note
如果希望使用不同的用户数据源,可以更改realm实现。 所提供的`UserDatabaseRealm`可以从JDBC数据库获取用户信息。

A0A3832E-663B-47A6-B108-78F36B608B77