Spring Security 的用户名别名

Posted

技术标签:

【中文标题】Spring Security 的用户名别名【英文标题】:Username alias with Spring Security 【发布时间】:2014-08-12 22:39:25 【问题描述】:

是否可以为用户提供使用普通用户名或其他用户名登录的能力?

我需要该功能的原因如下。我们使用电子邮件作为用户名(客户的要求),对于同一用户,它们都作为user@mail.domain.comuser@domain.com 有效。其中一些过去使用第一种表示法,另一些则使用第二种表示法。

用户正在通过LDAP 进行身份验证,这对我来说是只读的,所以我不能只在用户记录中添加第二个邮件属性。请问有什么想法吗?

【问题讨论】:

【参考方案1】:

我最终得到的解决方案是基于这个答案:https://***.com/a/1422202/711031。我使用以下FilteredRequest 实现:

public class LoginDomainCutFilter implements Filter         
    public void init(FilterConfig arg0) throws ServletException 
    

    public void destroy()         
    

    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException 
        chain.doFilter(new FilteredRequest(request), response);
    

    private static class FilteredRequest extends HttpServletRequestWrapper 
        public FilteredRequest(ServletRequest request) 
            super((HttpServletRequest) request);
        

        public String getParameter(String paramName) 
            String value = super.getParameter(paramName);
            if ("j_username".equals(paramName)) 
                value = cutSuffix(value, "@mail.domain.com");
                value = cutSuffix(value, "@domain.com");
            
            return value;
        

        private String cutSuffix(String value, String suffix) 
            if (value.endsWith(suffix)) value = value.substring(0, value.length() - suffix.length());
            return value;
        
    

在这种情况下,我们应该在web.xml 注册我们的过滤器 Spring Security 过滤器之前:

<filter>
    <filter-name>loginDomainCutFilter</filter-name>
    <filter-class>org.mydomain.myapp.LoginDomainCutFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>loginDomainCutFilter</filter-name>
    <url-pattern>/j_spring_security_check</url-pattern>
</filter-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

最后一步是将 LDAP 搜索过滤器中的 (mail=0) 更改为 (mail=0@*)

<beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
    <beans:constructor-arg index="0" value="ou=users,ou=myorgunit"/>      
    <beans:constructor-arg index="1" value="(mail=0@*)"/>
    <beans:constructor-arg index="2" ref="contextSource"/>
    <beans:property name="searchSubtree" value="true"/>
</beans:bean>

请注意,该解决方案的副作用是 Spring Security 用户名将不再包含 @domain 后缀,因此在需要显示电子邮件时应手动添加。但是,您应该决定哪个是主要的。

您还应该注意,过滤器不会影响包含另一个域后缀或根本没有后缀的用户名。这样做是有目的的,您可以为此添加一个简单的检查。

现在用户可以使用user@mail.domain.comuser@domain.com 甚至user 登录。如果您不喜欢后者的“奖励行为”,您还可以添加支票。

【讨论】:

以上是关于Spring Security 的用户名别名的主要内容,如果未能解决你的问题,请参考以下文章

Spring-Security:升级到 Spring-Security 4.1 后,用户名发送为空以进行登录

Spring Security拦截后恢复用户名

页面获取Spring Security登录用户

Spring Security 设置登录的用户名和密码的三种方式

Spring 安全认证:获取没有 SPRING_SECURITY_LAST_USERNAME 的用户名

spring-security 如何使用用户名或邮箱登录