当前位置: 首页 > 知识库问答 >
问题:

通过URL进行Spring Security认证

濮升
2023-03-14

我有一个Spring MVC应用程序,它使用Spring Security性和基于表单的登录进行授权/身份验证。

现在我想添加一个特殊的URL,其中包括一个令牌,该令牌应该可以在没有其他信息的情况下访问,因为该令牌对用户来说是唯一的:

http://myserver.com/special/5f6be0c0-87d7-11e2-9e96-0800200c9a66/text.pdf

如何配置Spring Security以使用该令牌进行用户身份验证?

共有3个答案

翟英达
2023-03-14

我遇到了这个问题,并使用Spring Security RembereMe服务基础设施的自定义实现解决了它。以下是你需要做的。

>

  • 定义自己的Authentication对象

    公共类LinkAuthentication扩展了AbstractAuthenticationToken{@Override public Object getCredentials(){return null;}

    @Override
    public Object getPrincipal()
    {
    
        return the prncipal that that is passed in via the constructor 
    }
    

    }

    定义

    public class LinkRememberMeService implements RememberMeServices, LogoutHandler
    {    
        /**
         * It might appear that once this method is called and returns an authentication object, that authentication should be finished and the
         * request should proceed. However, spring security does not work that way.
         * 
         * Once this method returns a non null authentication object, spring security still wants to run it through its authentication provider
         * which, is totally brain dead on the part of Spring this, is why there is also a
         * LinkAuthenticationProvider
         * 
         */
        @Override
        public Authentication autoLogin(HttpServletRequest request, HttpServletResponse response)
        {
            String accessUrl = ServletUtils.getApplicationUrl(request, "/special/");
            String requestUrl = request.getRequestURL().toString();
            if (requestUrl.startsWith(accessUrl))
            {
                // take appart the url extract the token, find the user details object 
                        // and return it. 
                LinkAuthentication linkAuthentication = new LinkAuthentication(userDetailsInstance);
                return linkAuthentication;
            } else
            {
                return null;
            }
        }
    
        @Override
        public void loginFail(HttpServletRequest request, HttpServletResponse response)
        {
        }
    
        @Override
        public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication)
        {
        }
    
        @Override
        public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
        {
        }
    }
    
    
    public class LinkAuthenticationProvider implements AuthenticationProvider
    {
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException
        {
            // Spring Security is totally brain dead and over engineered
            return authentication;
        }
    
        @Override
        public boolean supports(Class<?> authentication)
        {
            return LinkAuthentication.class.isAssignableFrom(authentication);
        }
    
    }
    

    破解Spring security xml的其余部分以定义自定义身份验证提供程序和自定义记住我服务。

    另外,如果对URL中的GUID进行base64编码,它将缩短几个字符。您可以使用Apache commons编解码器base64二进制编码器/解码器进行更安全的url链接。

    public static String toBase64Url(UUID uuid)
    {
        return Base64.encodeBase64URLSafeString(toBytes(uuid));
    }
    

  • 宋俊民
    2023-03-14

    您可以提供自定义PreAuthenticatedProcessingFilter和PreAuthenticatedAuthenticationProvider。有关详细信息,请参阅预身份验证方案章节。

    王昆
    2023-03-14

    您需要定义自定义预验证过滤器。

    超文本传输协议标签内的安全应用上下文中:

    <custom-filter position="PRE_AUTH_FILTER" ref="preAuthTokenFilter" />
    

    然后定义过滤器bean(及其适当的属性):

    <beans:bean class="com.yourcompany.PreAuthTokenFilter"
          id="preAuthTokenFilter">
        <beans:property name="authenticationDetailsSource" ref="authenticationDetailsSource" />
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="authenticationEntryPoint" ref="authenticationEntryPoint"/>
    </beans:bean>
    

    创建从GenericFilterBean扩展的自定义筛选器

    public class PreAuthTokenFilter extends GenericFilterBean {
    
    private AuthenticationEntryPoint authenticationEntryPoint;
    private AuthenticationManager authenticationManager;
    private AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource();
    
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
    
        String token = getTokenFromHeader(request);//your method
    
        if (StringUtils.isNotEmpty(token)) {
            /* get user entity from DB by token, retrieve its username and password*/
    
            if (isUserTokenValid(/* some args */)) {
                try {
                    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                    authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
                    Authentication authResult = this.authenticationManager.authenticate(authRequest);
                    SecurityContextHolder.getContext().setAuthentication(authResult);
                } catch (AuthenticationException e) {
                }
            }
        }
    
        chain.doFilter(request, response);
    }
    
    /*
    other methods
    */
    

    如果您不想要或无法检索密码,您需要创建自己的AbstractAuthenticationToken,它将仅接收用户名作为参数(主体)并使用它而不是UsernamePasswordAuthenticationToken

    public class PreAuthToken extends AbstractAuthenticationToken {
    
        private final Object principal;
    
        public PreAuthToken(Object principal) {
            super(null);
            super.setAuthenticated(true);
            this.principal = principal;
        }
    
        @Override
        public Object getCredentials() {
            return "";
        }
    
        @Override
        public Object getPrincipal() {
            return principal;
        }
    }
    
     类似资料:
    • 我正在尝试使用Spring Security UserDetailService身份验证使用电子邮件而不是用户名登录,但我无法登录并获取 org.springframework.security.authentication.内部身份验证服务异常。 调试代码时,调试器不会跟踪 用户user=userDao。findByUserName(用户电子邮件);来自UserServiceImpl。java和

    • 问题内容: 在(带有)中,我尝试使用以下语句通过基本身份验证访问我的网页: 但是Google Chrome浏览器在控制台中向我发出以下警告: [弃用]其URL包含嵌入式凭据(例如https://user:pass@host/)的子资源请求被阻止。有关更多详细信息,请参见https://www.chromestatus.com/feature/5669008342777856。 在标记的链接中提到该

    • 使用 Yubico OTP 进行双因素验证(服务端) 提高环境安全的第一步是提高客户端安全性(利用 PIV 进行 SSH 认证)和简化服务器上的管理任务(通过用户证书进行 SSH 认证),不过它们依然只依赖一个契机进行认证,是时候让双因素认证改变这一切了。 在远程服务器上为 SSH 或 sudo 启用双因素认证需要进行线上验证。验证服务可以选择使用由 YubiCloud 提供的 YubiHSM(硬

    • 本文向大家介绍通过jquery 获取URL参数并进行转码,包括了通过jquery 获取URL参数并进行转码的使用技巧和注意事项,需要的朋友参考一下 jquery 获取URL参数并转码,首先构造一个含有目标参数的正则表达式对象,匹配目标参数并返回参数值 代码如下: 测试url:http://xxxx.html?picture="XXXX"&content="你好!"

    • 赋值运算符(=)可以将一个对象赋给另一个相同类型的对象。这种赋值默认通过成员复制(memberwisecopy)进行,对象的每个成虽一一复制给另一对象的同一成员(如图6.L1)(注意:如果类的数据成员包含动态分配存储体,则通过默认的成员复制赋值可能导致严重问题,第8章“运算符重载”中将介绍这些问题及其处理方法)。 对象可以作为函数参数传递并从函数返回。这种传递和返回默认按值调用进行,即传递和返回对

    • 测试 如果你允许 root 用户登录,你应该能够通过暴露的 2222 端口连接到容器: ❯ ssh root@127.0.0.1 -p 2222 Authenticated with partial success. root@127.0.0.1 password: 你如果看到 Authenticated with partial success 的提示,这就表示对公钥的认证已经成功了。 现在,请