⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 digestprocessingfilter.java

📁 acegi构造安全的java系统
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
            // Check signature of nonce matches this expiry time            String expectedNonceSignature = DigestUtils.md5Hex(nonceExpiryTime + ":"                    + this.getAuthenticationEntryPoint().getKey());            if (!expectedNonceSignature.equals(nonceTokens[1])) {                fail(request, response,                        new BadCredentialsException(messages.getMessage("DigestProcessingFilter.nonceCompromised",                                new Object[]{nonceAsPlainText}, "Nonce token compromised {0}")));                return;            }            // Lookup password for presented username            // NB: DAO-provided password MUST be clear text - not encoded/salted            // (unless this instance's passwordAlreadyEncoded property is 'false')            boolean loadedFromDao = false;            UserDetails user = userCache.getUserFromCache(username);            if (user == null) {                loadedFromDao = true;                try {                    user = userDetailsService.loadUserByUsername(username);                } catch (UsernameNotFoundException notFound) {                    fail(request, response,                            new BadCredentialsException(messages.getMessage("DigestProcessingFilter.usernameNotFound",                                    new Object[]{username}, "Username {0} not found")));                    return;                }                if (user == null) {                    throw new AuthenticationServiceException(                            "AuthenticationDao returned null, which is an interface contract violation");                }                userCache.putUserInCache(user);            }            // Compute the expected response-digest (will be in hex form)            String serverDigestMd5;            // Don't catch IllegalArgumentException (already checked validity)            serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(),                    ((HttpServletRequest) request).getMethod(), uri, qop, nonce, nc, cnonce);            // If digest is incorrect, try refreshing from backend and recomputing            if (!serverDigestMd5.equals(responseDigest) && !loadedFromDao) {                if (logger.isDebugEnabled()) {                    logger.debug(                            "Digest comparison failure; trying to refresh user from DAO in case password had changed");                }                try {                    user = userDetailsService.loadUserByUsername(username);                } catch (UsernameNotFoundException notFound) {                    // Would very rarely happen, as user existed earlier                    fail(request, response,                            new BadCredentialsException(messages.getMessage("DigestProcessingFilter.usernameNotFound",                                    new Object[]{username}, "Username {0} not found")));                }                userCache.putUserInCache(user);                // Don't catch IllegalArgumentException (already checked validity)                serverDigestMd5 = generateDigest(passwordAlreadyEncoded, username, realm, user.getPassword(),                        ((HttpServletRequest) request).getMethod(), uri, qop, nonce, nc, cnonce);            }            // If digest is still incorrect, definitely reject authentication attempt            if (!serverDigestMd5.equals(responseDigest)) {                if (logger.isDebugEnabled()) {                    logger.debug("Expected response: '" + serverDigestMd5 + "' but received: '" + responseDigest                            + "'; is AuthenticationDao returning clear text passwords?");                }                fail(request, response,                        new BadCredentialsException(messages.getMessage("DigestProcessingFilter.incorrectResponse",                                "Incorrect response")));                return;            }            // To get this far, the digest must have been valid            // Check the nonce has not expired            // We do this last so we can direct the user agent its nonce is stale            // but the request was otherwise appearing to be valid            if (nonceExpiryTime < System.currentTimeMillis()) {                fail(request, response,                        new NonceExpiredException(messages.getMessage("DigestProcessingFilter.nonceExpired",                                "Nonce has expired/timed out")));                return;            }            if (logger.isDebugEnabled()) {                logger.debug("Authentication success for user: '" + username + "' with response: '" + responseDigest                        + "'");            }            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(user,                    user.getPassword());            authRequest.setDetails(authenticationDetailsSource.buildDetails((HttpServletRequest) request));            SecurityContextHolder.getContext().setAuthentication(authRequest);        }        chain.doFilter(request, response);    }    public static String encodePasswordInA1Format(String username, String realm, String password) {        String a1 = username + ":" + realm + ":" + password;        String a1Md5 = new String(DigestUtils.md5Hex(a1));        return a1Md5;    }    private void fail(ServletRequest request, ServletResponse response, AuthenticationException failed)            throws IOException, ServletException {        SecurityContextHolder.getContext().setAuthentication(null);        if (logger.isDebugEnabled()) {            logger.debug(failed);        }        authenticationEntryPoint.commence(request, response, failed);    }    /**     * Computes the <code>response</code> portion of a Digest authentication header. Both the server and user     * agent should compute the <code>response</code> independently. Provided as a static method to simplify the     * coding of user agents.     *     * @param passwordAlreadyEncoded true if the password argument is already encoded in the correct format. False if     *                               it is plain text.     * @param username               the user's login name.     * @param realm                  the name of the realm.     * @param password               the user's password in plaintext or ready-encoded.     * @param httpMethod             the HTTP request method (GET, POST etc.)     * @param uri                    the request URI.     * @param qop                    the qop directive, or null if not set.     * @param nonce                  the nonce supplied by the server     * @param nc                     the "nonce-count" as defined in RFC 2617.     * @param cnonce                 opaque string supplied by the client when qop is set.     * @return the MD5 of the digest authentication response, encoded in hex     * @throws IllegalArgumentException if the supplied qop value is unsupported.     */    public static String generateDigest(boolean passwordAlreadyEncoded, String username, String realm, String password,                                        String httpMethod, String uri, String qop, String nonce, String nc, String cnonce)            throws IllegalArgumentException {        String a1Md5 = null;        String a2 = httpMethod + ":" + uri;        String a2Md5 = new String(DigestUtils.md5Hex(a2));        if (passwordAlreadyEncoded) {            a1Md5 = password;        } else {            a1Md5 = encodePasswordInA1Format(username, realm, password);        }        String digest;        if (qop == null) {            // as per RFC 2069 compliant clients (also reaffirmed by RFC 2617)            digest = a1Md5 + ":" + nonce + ":" + a2Md5;        } else if ("auth".equals(qop)) {            // As per RFC 2617 compliant clients            digest = a1Md5 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2Md5;        } else {            throw new IllegalArgumentException("This method does not support a qop: '" + qop + "'");        }        String digestMd5 = new String(DigestUtils.md5Hex(digest));        return digestMd5;    }    public DigestProcessingFilterEntryPoint getAuthenticationEntryPoint() {        return authenticationEntryPoint;    }    public UserCache getUserCache() {        return userCache;    }    public UserDetailsService getUserDetailsService() {        return userDetailsService;    }    public void init(FilterConfig ignored) throws ServletException {    }    public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) {        Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required");        this.authenticationDetailsSource = authenticationDetailsSource;    }    public void setAuthenticationEntryPoint(DigestProcessingFilterEntryPoint authenticationEntryPoint) {        this.authenticationEntryPoint = authenticationEntryPoint;    }    public void setMessageSource(MessageSource messageSource) {        this.messages = new MessageSourceAccessor(messageSource);    }    public void setPasswordAlreadyEncoded(boolean passwordAlreadyEncoded) {        this.passwordAlreadyEncoded = passwordAlreadyEncoded;    }    public void setUserCache(UserCache userCache) {        this.userCache = userCache;    }    public void setUserDetailsService(UserDetailsService userDetailsService) {        this.userDetailsService = userDetailsService;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -