最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring?Security中用戶名和密碼的驗證完整流程

 更新時間:2025年06月27日 15:36:59   作者:咖啡味巧克力  
本文給大家介紹Spring?Security中用戶名和密碼的驗證完整流程,本文結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,感興趣的朋友一起看看吧

首先創(chuàng)建了一個UsernamePasswordAuthenticationToken對象,這是Spring Security中用于表示基于用戶名和密碼的認證請求的一個類。這個對象被初始化時,接收了兩個參數(shù):username(用戶名)和password(密碼)。這兩個參數(shù)代表了用戶嘗試登錄時提供的憑證。

接下來,通過調(diào)用authenticationManager的authenticate方法,并傳入前面創(chuàng)建的authenticationToken對象,來執(zhí)行認證過程。authenticationManager是Spring Security中的一個核心接口,它負責處理認證請求。在調(diào)用authenticate方法時,Spring Security會基于配置的安全策略(比如從數(shù)據(jù)庫、LDAP服務(wù)器或其他認證源中檢索用戶信息,并驗證提供的密碼是否正確)來驗證用戶提供的憑證是否有效
如果認證成功,authenticate方法會返回一個填充了用戶權(quán)限等詳細信息的Authentication對象。這個對象代表了認證成功后的用戶會話,包含了用戶的身份信息、權(quán)限、是否已記住我(remember-me)等詳細信息。

如果認證失敗,authenticate方法會拋出一個AuthenticationException異常,這通常意味著提供的用戶名或密碼不正確,或者用戶賬戶處于鎖定、禁用等狀態(tài)。

  /**
     * 登錄驗證
     * 
     * @param username 用戶名
     * @param password 密碼
     * @param code 驗證碼
     * @param uuid 唯一標識
     * @return 結(jié)果
     */
    public String login(String username, String password, String code, String uuid)
    {
        // 驗證碼校驗
        validateCaptcha(username, code, uuid);
        // 登錄前置校驗
        loginPreCheck(username, password);
        // 用戶驗證
        Authentication authentication = null;
        try
        {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 該方法會去調(diào)用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        }
        catch (Exception e)
        {
            if (e instanceof BadCredentialsException)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
                throw new UserPasswordNotMatchException();
            }
            else
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
                throw new ServiceException(e.getMessage());
            }
        }
        finally
        {
            //清理認證上下文,確保線程上下文中的認證信息被清除,避免潛在的內(nèi)存泄漏或安全問題
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        //從認證成功的Authentication對象中獲取Principal,并將其強制轉(zhuǎn)換為LoginUser對象。LoginUser是一個自定義類,通常包含用戶的基本信息和權(quán)限信息
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
         //調(diào)用recordLoginInfo方法記錄用戶的登錄信息,例如登錄時間、IP地址等
        recordLoginInfo(loginUser.getUserId());
        // 生成token,為用戶生成一個Token,并返回該Token。Token通常用于后續(xù)的用戶身份驗證和授權(quán)
        return tokenService.createToken(loginUser);
    }

驗證碼校驗方法

 /**
     * 校驗驗證碼
     * 
     * @param username 用戶名
     * @param code 驗證碼
     * @param uuid 唯一標識
     * @return 結(jié)果
     */
    public void validateCaptcha(String username, String code, String uuid)
    {
        boolean captchaEnabled = configService.selectCaptchaEnabled();
        if (captchaEnabled)
        {
            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
            String captcha = redisCache.getCacheObject(verifyKey);
            if (captcha == null)
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
                throw new CaptchaExpireException();
            }
            redisCache.deleteObject(verifyKey);
            if (!code.equalsIgnoreCase(captcha))
            {
                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
                throw new CaptchaException();
            }
        }
    }

用戶名和密碼校驗代碼

 /**
     * 登錄前置校驗
     * @param username 用戶名
     * @param password 用戶密碼
     */
    public void loginPreCheck(String username, String password)
    {
        // 用戶名或密碼為空 錯誤
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }
        // 密碼如果不在指定范圍內(nèi) 錯誤
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }
        // 用戶名不在指定范圍內(nèi) 錯誤
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }
        // IP黑名單校驗
        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
            throw new BlackListException();
        }
    }

記錄登錄信息代碼

 /**
     * 記錄登錄信息
     *
     * @param userId 用戶ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(IpUtils.getIpAddr());
        sysUser.setLoginDate(DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);
    }

UserDetailsServiceImpl實現(xiàn)類的代碼,UserDetailsService是java自帶的類,UserDetailsServiceImpl繼承UserDetailsService的loadUserByUsername方法 

/**
 * 用戶驗證處理
 *
 * @author ruoyi
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService
{
    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
    @Autowired
    private ISysUserService userService;
    @Autowired
    private SysPasswordService passwordService;
    @Autowired
    private SysPermissionService permissionService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
    {
        SysUser user = userService.selectUserByUserName(username);
        if (StringUtils.isNull(user))
        {
            log.info("登錄用戶:{} 不存在.", username);
            throw new ServiceException(MessageUtils.message("user.not.exists"));
        }
        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            log.info("登錄用戶:{} 已被刪除.", username);
            throw new ServiceException(MessageUtils.message("user.password.delete"));
        }
        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            log.info("登錄用戶:{} 已被停用.", username);
            throw new ServiceException(MessageUtils.message("user.blocked"));
        }
        passwordService.validate(user);
        return createLoginUser(user);
    }
    public UserDetails createLoginUser(SysUser user)
    {
        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
    }
}

到此這篇關(guān)于在Spring Security中,用戶名和密碼的驗證流程的文章就介紹到這了,更多相關(guān)Spring Security用戶名和密碼驗證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • mybatis-flex實現(xiàn)鏈式操作的示例代碼

    mybatis-flex實現(xiàn)鏈式操作的示例代碼

    MyBatis-Flex它提供了一種鏈式操作方式,本文主要介紹了mybatis-flex實現(xiàn)鏈式操作的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • java中堆和棧的區(qū)別分析

    java中堆和棧的區(qū)別分析

    這篇文章主要介紹了java中堆和棧的區(qū)別,分析了Java中堆和棧的原理及使用時的注意事項,需要的朋友可以參考下
    2014-09-09
  • HttpServletResponse亂碼問題_動力節(jié)點Java學(xué)院整理

    HttpServletResponse亂碼問題_動力節(jié)點Java學(xué)院整理

    這篇文章主要介紹了HttpServletResponse亂碼問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • SpringBoot自動重啟的兩種方法

    SpringBoot自動重啟的兩種方法

    我們在項目開發(fā)階段,可能經(jīng)常會修改代碼,修改完后就要重啟Spring Boot,本文主要介紹了SpringBoot自動重啟的兩種方法,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12
  • 詳解Java中的Reflection反射和暴力反射

    詳解Java中的Reflection反射和暴力反射

    本文主要介紹了詳解Java中的Reflection反射和暴力反射,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • 簡單記事本java源碼實例

    簡單記事本java源碼實例

    這篇文章主要介紹了簡單記事本java源碼,以一個完整的實例形式分析了記事本的Java實現(xiàn)方法,對于Java應(yīng)用程序的開發(fā)有一定的參考借鑒價值,需要的朋友可以參考下
    2014-11-11
  • Java使用itext生成pdf標簽的操作方法

    Java使用itext生成pdf標簽的操作方法

    iText是著名的開放源碼的站點sourceforge一個項目,是用于生成PDF文檔的一個java類庫,通過iText不僅可以生成PDF或rtf的文檔,而且可以將XML、Html文件轉(zhuǎn)化為PDF文件,本文給大家介紹了Java使用itext生成pdf標簽的操作方法,需要的朋友可以參考下
    2024-12-12
  • SpringMVC上傳文件并保存到本地代碼實例

    SpringMVC上傳文件并保存到本地代碼實例

    這篇文章主要介紹了SpringMVC上傳文件并保存到本地代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Java使用選擇排序法對數(shù)組排序?qū)崿F(xiàn)代碼

    Java使用選擇排序法對數(shù)組排序?qū)崿F(xiàn)代碼

    這篇文章主要介紹了Java使用選擇排序法對數(shù)組排序?qū)崿F(xiàn)代碼,需要的朋友可以參考下
    2014-02-02
  • java md5工具類分享

    java md5工具類分享

    這篇文章主要介紹了java的md5工具類,需要的朋友可以參考下
    2014-02-02

最新評論

三明市| 镇康县| 垦利县| 蓬安县| 柘荣县| 无极县| 遂平县| 云南省| 繁峙县| 时尚| 虎林市| 潼南县| 江川县| 全南县| 新田县| 临武县| 神农架林区| 宝鸡市| 文安县| 宁河县| 沙河市| 成安县| 教育| 瓮安县| 洛阳市| 任丘市| 中卫市| 潜山县| 昌都县| 宁远县| 顺义区| 陇南市| 罗江县| 禄劝| 游戏| 招远市| 黔东| 类乌齐县| 绥江县| 察哈| 安福县|