证实原通晓析金沙8331网址

本文实例陈诉了jquery达成鼠标滑过小图时彰显大图的办法。分享给大家供大家参谋。具体落到实处情势如下:

在 UsernamePasswordAuthenticationFilter
源码深入分析
中,最终在类UsernamePasswordAuthenticationFilter 的申明格局
attemptAuthentication()
会将顾客表单提交过来的客户名和密码封装成对象委托类
AuthenticationManager 的认证方式 authenticate() 进行身份验证。

复制代码 代码如下:

那么本文首要对 AuthenticationManager 的认证措施 authenticate()
验证原理实行源码解析。

金沙8331网址 1

AuthenticationManager 相关类图

AuthenticationManager
验证进度涉及到的类和接口比较多,先用一张类图表明各类类和接口之间的关联,如下:

金沙8331网址 2

AuthenticationManager相关类图.png

  • AuthenticationManager 为认证处理接口类,其定义了评释方式
    authenticate()证实原通晓析金沙8331网址。。
  • ProviderManager 为认证管理类,达成了接口 AuthenticationManager
    ,并在表达方法 authenticate() 中将地点评释委托给全体验证资格的
    AuthenticationProvider 进行身份验证。
    ProviderManager中的成员变量
    providers [List<AuthenticationProvider>] 存款和储蓄了二个
    AuthenticationProvider 类型的 List,和 spring security
    配置文件相呼应,如下图:

金沙8331网址 3

AuthenticationManager 对比图

  • AuthenticationProvider 为认证接口类,其定义了身价验证格局
    authenticate()
  • AbstractUserDetailsAuthenticationProvider 为认证抽象类,达成了接口
    AuthenticationProvider 定义的表明方法 authenticate()
    AbstractUserDetailsAuthenticationProvider 还定义了设想方法
    retrieveUser() 用作查询数据库顾客音信,以致虚构方法
    additionalAuthenticationChecks() 用作身份认证。
  • DaoAuthenticationProvider 世袭自类
    AbstractUserDetailsAuthenticationProvider,完毕该类的法子
    retrieveUser()additionalAuthenticationChecks()
    DaoAuthenticationProvider 中还具有成员变量
    userDetailsService [UserDetailsService]
    用功能户音讯查询,以至成员变量 passwordEncoder [PasswordEncoder]
    用作密码的加密及表明。
    DaoAuthenticationProviderspring security
    配置文件相呼应,如下图所示:

金沙8331网址 4

authenticationProvider 对比图

盼望本文所述对我们的jQuery程序设计有所扶植。

流程深入分析

1、认证的输入为 AuthenticationManagerauthenticate()方法,鉴于
AuthenticationManager是接口类,因此剖判它的兑现类
ProviderManagerProviderManagerauthenticate() 方法代码如下:

    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        Class<? extends Authentication> toTest = authentication.getClass();
        AuthenticationException lastException = null;
        Authentication result = null;
        boolean debug = logger.isDebugEnabled();

-->1    for (AuthenticationProvider provider : getProviders()) {
            if (!provider.supports(toTest)) {
                continue;
            }

            if (debug) {
                logger.debug("Authentication attempt using "
                        + provider.getClass().getName());
            }

            try {
-->2            result = provider.authenticate(authentication);

                if (result != null) {
                    copyDetails(authentication, result);
                    break;
                }
            }
            catch (AccountStatusException e) {
                prepareException(e, authentication);
                // SEC-546: Avoid polling additional providers if auth failure is due to
                // invalid account status
                throw e;
            }
            catch (InternalAuthenticationServiceException e) {
                prepareException(e, authentication);
                throw e;
            }
            catch (AuthenticationException e) {
                lastException = e;
            }
        }

        if (result == null && parent != null) {
            // Allow the parent to try.
            try {
                result = parent.authenticate(authentication);
            }
            catch (ProviderNotFoundException e) {
                // ignore as we will throw below if no other exception occurred prior to
                // calling parent and the parent
                // may throw ProviderNotFound even though a provider in the child already
                // handled the request
            }
            catch (AuthenticationException e) {
                lastException = e;
            }
        }

        if (result != null) {
            if (eraseCredentialsAfterAuthentication
                    && (result instanceof CredentialsContainer)) {
                // Authentication is complete. Remove credentials and other secret data
                // from authentication
                ((CredentialsContainer) result).eraseCredentials();
            }

            eventPublisher.publishAuthenticationSuccess(result);
            return result;
        }

        // Parent was null, or didn't authenticate (or throw an exception).

        if (lastException == null) {
            lastException = new ProviderNotFoundException(messages.getMessage(
                    "ProviderManager.providerNotFound",
                    new Object[] { toTest.getName() },
                    "No AuthenticationProvider found for {0}"));
        }

        prepareException(lastException, authentication);

        throw lastException;
    }

其中:

  • -->1 处的 for 循环从该类的属性
    providers[List<AuthenticationProvider>] 中去取到支撑该认证的
    AuthenticationProvider 来进展表达处理。
  • -->2 处代码为运用援助该认证的 AuthenticationProvider
    对客商身份打开认证,使用该类进行验证如下文所示。

2、在上文代码的 -->2 处调用的代码
result = provider.authenticate(authentication);,使用了
AuthenticationProviderauthenticate()
方法开展认证,接下去解析该格局,鉴于 AuthenticationProvider
是一个接口,由此解析它的落实类
AbstractUserDetailsAuthenticationProvider 的子类
DaoAuthenticationProvider 的辨证方式 authenticate(),代码如下所示:

public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
                messages.getMessage(
                        "AbstractUserDetailsAuthenticationProvider.onlySupports",
                        "Only UsernamePasswordAuthenticationToken is supported"));

        // Determine username
        String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
                : authentication.getName();

        boolean cacheWasUsed = true;
        UserDetails user = this.userCache.getUserFromCache(username);

        if (user == null) {
            cacheWasUsed = false;

            try {
-->1            user = retrieveUser(username,
                        (UsernamePasswordAuthenticationToken) authentication);
            }
            catch (UsernameNotFoundException notFound) {
                logger.debug("User '" + username + "' not found");

                if (hideUserNotFoundExceptions) {
                    throw new BadCredentialsException(messages.getMessage(
                            "AbstractUserDetailsAuthenticationProvider.badCredentials",
                            "Bad credentials"));
                }
                else {
                    throw notFound;
                }
            }

            Assert.notNull(user,
                    "retrieveUser returned null - a violation of the interface contract");
        }

        try {
            preAuthenticationChecks.check(user);
-->2        additionalAuthenticationChecks(user,
                    (UsernamePasswordAuthenticationToken) authentication);
        }
        catch (AuthenticationException exception) {
            if (cacheWasUsed) {
                // There was a problem, so try again after checking
                // we're using latest data (i.e. not from the cache)
                cacheWasUsed = false;
                user = retrieveUser(username,
                        (UsernamePasswordAuthenticationToken) authentication);
                preAuthenticationChecks.check(user);
                additionalAuthenticationChecks(user,
                        (UsernamePasswordAuthenticationToken) authentication);
            }
            else {
                throw exception;
            }
        }

        postAuthenticationChecks.check(user);

        if (!cacheWasUsed) {
            this.userCache.putUserInCache(user);
        }

        Object principalToReturn = user;

        if (forcePrincipalAsString) {
            principalToReturn = user.getUsername();
        }

        return createSuccessAuthentication(principalToReturn, authentication, user);
    }

其中:

  • -->1 处的代码表示调用方法 retrieveUser()
    从数据库中加载顾客消息。该方法代码如下:

protected final UserDetails retrieveUser(String username,
            UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        UserDetails loadedUser;

        try {
-->1.1  loadedUser = this.getUserDetailsService().loadUserByUsername(username);
        }
        catch (UsernameNotFoundException notFound) {
            if (authentication.getCredentials() != null) {
                String presentedPassword = authentication.getCredentials().toString();
                passwordEncoder.isPasswordValid(userNotFoundEncodedPassword,
                        presentedPassword, null);
            }
            throw notFound;
        }
        catch (Exception repositoryProblem) {
            throw new InternalAuthenticationServiceException(
                    repositoryProblem.getMessage(), repositoryProblem);
        }

        if (loadedUser == null) {
            throw new InternalAuthenticationServiceException(
                    "UserDetailsService returned null, which is an interface contract violation");
        }
        return loadedUser;
    }

在上述代码中 -->1.1 处代码的情趣为:调用成员变量 userDetailsService
的方法 loadUserByUsername() 加载数据层中的客商音讯(是还是不是很纯熟)。

  • -->2 处的代码为调用方法 additionalAuthenticationChecks()
    密码验证,该措施代码如下:

protected void additionalAuthenticationChecks(UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        Object salt = null;

        if (this.saltSource != null) {
            salt = this.saltSource.getSalt(userDetails);
        }

        if (authentication.getCredentials() == null) {
            logger.debug("Authentication failed: no credentials provided");

            throw new BadCredentialsException(messages.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials",
                    "Bad credentials"));
        }

        String presentedPassword = authentication.getCredentials().toString();
->2.1 if (!passwordEncoder.isPasswordValid(userDetails.getPassword(),
                presentedPassword, salt)) {
            logger.debug("Authentication failed: password does not match stored value");

            throw new BadCredentialsException(messages.getMessage(
                    "AbstractUserDetailsAuthenticationProvider.badCredentials",
                    "Bad credentials"));
        }
    }

->2.1 出代码调用了成员变量 passwordEncoder 的校验方法
isPasswordValid() 对客商密码举行表达。(是还是不是很纯熟)

金沙8331网址 5

AuthenticationManager 流程图.png

参考

  • spring security
    源码
  • spring security
    API

发表评论

电子邮件地址不会被公开。 必填项已用*标注