配置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
CustomPrincipal.javapublic 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
CustomHttpServletRequest.javapublic 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
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
frontend/my-login.tsimport { 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
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,adminSource 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
$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