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

Spring Security自定義認(rèn)證器的實現(xiàn)代碼

 更新時間:2022年06月24日 08:43:01   作者:阿弱  
這篇文章主要介紹了Spring Security自定義認(rèn)證器的實現(xiàn)代碼,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

在了解過Security的認(rèn)證器后,如果想自定義登陸,只要實現(xiàn)AuthenticationProvider還有對應(yīng)的Authentication就可以了

Authentication

首先要創(chuàng)建一個自定義的Authentication,Security提供了一個Authentication的子類AbstractAuthenticationToken

我們實現(xiàn)這個類可以了,他已經(jīng)實現(xiàn)了Authentication的一些方法

public class NamePassAuthenticationToken extends AbstractAuthenticationToken {

    private static final long serialVersionUID = 520L;
    private final Object principal;
    private Object credentials;

//提供第一次進(jìn)來的構(gòu)造方法
    public NamePassAuthenticationToken(Object principal, Object credentials) {
        super((Collection)null);
        this.principal = principal;
        this.credentials = credentials;
        this.setAuthenticated(false);
    }

//提供填充Authentication的構(gòu)造方法
    public NamePassAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        super.setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return this.credentials;
    }

    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    @Override
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        if (isAuthenticated) {
            throw new IllegalArgumentException("Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        } else {
            super.setAuthenticated(false);
        }
    }

    @Override
    public void eraseCredentials() {
        super.eraseCredentials();
        this.credentials = null;
    }
}

這個類關(guān)鍵就是一個是認(rèn)證的,一個沒認(rèn)證的的構(gòu)造器

AuthenticationProvider

接著是AuthenticationProvider,需要實現(xiàn)他的authenticate方法

@Setter
public class NamePassAuthenticationProvider implements AuthenticationProvider {

    private CustomUserDetailsService userDetailsService;

    private PasswordEncoder passwordEncoder;

    @Override
    //具體認(rèn)證邏輯
    public Authentication authenticate(Authentication authentication) {
        NamePassAuthenticationToken authenticationToken = (NamePassAuthenticationToken) authentication;
        String username = (String) authenticationToken.getPrincipal();
        String password = (String) authenticationToken.getCredentials();
        //讓具體認(rèn)證類去認(rèn)證
        UserDetails user = userDetailsService.loadUserByUsername(username); 
        boolean matches = passwordEncoder.matches(password, user.getPassword());
        if (!matches) {
            ResMsg.throwException(AuthExceptionGroup.AUTH_ERROR);
        }
        //填充Authentication
        NamePassAuthenticationToken authenticationResult = new NamePassAuthenticationToken(user, password, user.getAuthorities());
        authenticationResult.setDetails(authenticationToken.getDetails());
        return authenticationResult;
    }

    @Override
    //指定具體的Authentication
    //根據(jù)你指定的Authentication來找到具體的Provider
    public boolean supports(Class<?> authentication) {
        return NamePassAuthenticationToken.class.isAssignableFrom(authentication);
    }
}

SecurityConfigurerAdapter

接著就是填充配置了

@Component
public class NamePassAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(HttpSecurity http) {
        //phonePass provider
        NamePassAuthenticationProvider provider = new NamePassAuthenticationProvider();
        provider.setUserDetailsService(customUserDetailsService);
        provider.setPasswordEncoder(passwordEncoder);
        http.authenticationProvider(provider);
    }
}

接下來就是導(dǎo)入配置了

通常都會有一個實現(xiàn)了WebSecurityConfigurerAdapter的配置類

把配置類注入進(jìn)來

@Autowired
private NamePassAuthenticationSecurityConfig namePassAuthenticationSecurityConfig; 
    
protected void configure(HttpSecurity http) throws Exception {
  http.apply(namePassAuthenticationSecurityConfig);
}

UserDetailsService

UserDetailsService是具體的認(rèn)證實現(xiàn)類

這個類就非常熟悉了,只需要實現(xiàn)他的loadUserByUsername方法,就可以實現(xiàn)認(rèn)證了

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        AuthmsViewAccount account = accountService.getAccount(username);
        if(account == null) {
            ResMsg.throwException(AUTH_ERROR);
        }

        if (account.getStatus() != 1) {
            ResMsg.throwException(ACCOUNT_HAS_BANED);
        }

        String spliceStaffInfo = String.format("%d-%s",account.getAccountId(),account.getUsername());
//只要Collection<? extends GrantedAuthority> authorities
//這個參數(shù)不為空,就表明認(rèn)證通過,所以空集合也可以通過
        return new User(spliceStaffInfo,account.getPassword(), AuthorityUtils.NO_AUTHORITIES);
    }

把認(rèn)證結(jié)果填充到上下文中

TokenFilter

如果結(jié)合了Token,那么需要從token中識別該用戶

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

    String bearerToken = resolveToken(request);

    if (bearerToken != null && !"".equals(bearerToken.trim()) && SecurityContextHolder.getContext().getAuthentication() == null) {
        //從redis中獲取該用戶
        NamePassAuthenticationToken namePassAuthenticationToken = authRedisHelper.get(bearerToken);
        if(namePassAuthenticationToken != null) {
            //將信息保存到上下文中
 SecurityContextHolder.getContext().setAuthentication(namePassAuthenticationToken);
        }
    }

    chain.doFilter(request, response);
}

private String resolveToken(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
            return bearerToken.substring(7);
        }
        return null;
    }
public NamePassAuthenticationToken get(String bearerToken){
    String spliceStaffInfo = (String)redisRepository.get(formatKey(bearerToken));
    if(spliceStaffInfo == null) {
        return null;
    }
    return new NamePassAuthenticationToken(new AuthStaff(spliceStaffInfo),null,AuthorityUtils.NO_AUTHORITIES);
}

登錄過程

在登錄的時候,就需要用到這個自定義的認(rèn)證器了

// 通過用戶名和密碼創(chuàng)建一個 Authentication 認(rèn)證對象,實現(xiàn)類為 NamePassAuthenticationToken
NamePassAuthenticationToken authenticationToken = new NamePassAuthenticationToken(user.getUsername(), user.getPassword());

//通過 AuthenticationManager(默認(rèn)實現(xiàn)為ProviderManager)的authenticate方法驗證 Authentication 對象 
//AuthenticationManager會通過你傳入的authenticationToken來找到具體的Provider
Authentication authentication = authenticationManager.authenticate(authenticationToken);
//填充用戶信息到secrity中的user里
User principal = (User) authentication.getPrincipal();
//獲取認(rèn)證后的信息
NamePassAuthenticationToken namePassAuthenticationToken = new NamePassAuthenticationToken(new AuthStaff(principal.getUsername()), null, authentication.getAuthorities());
// 生成token
String bearerToken = IdUtil.fastSimpleUUID();
// 加載到reids
authRedisHelper.set(bearerToken, namePassAuthenticationToken);

這樣就實現(xiàn)了自定義的認(rèn)證器了

到此這篇關(guān)于Spring Security自定義認(rèn)證器的文章就介紹到這了,更多相關(guān)Spring Security自定義認(rèn)證器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?properties?和?yml?的區(qū)別解析

    Java?properties?和?yml?的區(qū)別解析

    properties和yml都是Spring?Boot支持的兩種配置文件,它們可以看做Spring?Boot在不同時期的兩種“產(chǎn)品”,這篇文章主要介紹了Java?properties?和?yml?的區(qū)別,需要的朋友可以參考下
    2023-02-02
  • java編程實現(xiàn)求質(zhì)數(shù)與因式分解代碼分享

    java編程實現(xiàn)求質(zhì)數(shù)與因式分解代碼分享

    這篇文章主要介紹了Java編程實現(xiàn)求質(zhì)數(shù)與因式分解代碼分享,對二者的概念作了簡單介紹(多此一舉,哈哈),都是小學(xué)數(shù)學(xué)老師的任務(wù),然后分享了求解質(zhì)數(shù)和因式分解的Java代碼,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • mybatisplus報Invalid bound statement (not found)錯誤的解決方法

    mybatisplus報Invalid bound statement (not found)錯誤的解決方法

    搭建項目時使用了mybatisplus,項目能夠正常啟動,但在調(diào)用mapper方法查詢數(shù)據(jù)庫時報Invalid bound statement (not found)錯誤。本文給大家分享解決方案,感興趣的朋友跟隨小編一起看看吧
    2020-08-08
  • Java里的static在Kotlin里如何實現(xiàn)

    Java里的static在Kotlin里如何實現(xiàn)

    這篇文章主要介紹了Java里的static在Kotlin里如何實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 安裝多個版本JDK后使用時的切換方法總結(jié)

    安裝多個版本JDK后使用時的切換方法總結(jié)

    我們平時在window上做開發(fā)的時候,可能需要同時開發(fā)兩個甚至多個項目,有時不同的項目對JDK的版本要求有區(qū)別,下面這篇文章主要給大家介紹了安裝多個版本JDK后使用的切換方法,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • 詳解Java是如何通過接口來創(chuàng)建代理并進(jìn)行http請求

    詳解Java是如何通過接口來創(chuàng)建代理并進(jìn)行http請求

    今天給大家?guī)淼闹R是關(guān)于Java的,文章圍繞Java是如何通過接口來創(chuàng)建代理并進(jìn)行http請求展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • SpringBoot Controller Post接口單元測試示例

    SpringBoot Controller Post接口單元測試示例

    今天小編就為大家分享一篇關(guān)于SpringBoot Controller Post接口單元測試示例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例

    SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例

    規(guī)則引擎其實是一種組件,它可以嵌入到程序當(dāng)中,將程序復(fù)雜的判斷規(guī)則從業(yè)務(wù)代碼中剝離出來,使得程序只需要關(guān)心自己的業(yè)務(wù),而不需要去進(jìn)行復(fù)雜的邏輯判斷,本文給大家介紹了SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例,需要的朋友可以參考下
    2024-12-12
  • Java經(jīng)典設(shè)計模式之適配器模式原理與用法詳解

    Java經(jīng)典設(shè)計模式之適配器模式原理與用法詳解

    這篇文章主要介紹了Java經(jīng)典設(shè)計模式之適配器模式,簡單說明了適配器模式的概念、原理,并結(jié)合實例形式分析了java適配器模式的用法與相關(guān)注意事項,需要的朋友可以參考下
    2017-08-08
  • Apache?log4j2-RCE?漏洞復(fù)現(xiàn)及修復(fù)建議(CVE-2021-44228)

    Apache?log4j2-RCE?漏洞復(fù)現(xiàn)及修復(fù)建議(CVE-2021-44228)

    Apache?Log4j2是一款Java日志框架,大量應(yīng)用于業(yè)務(wù)系統(tǒng)開發(fā)。2021年11月24日,阿里云安全團(tuán)隊向Apache官方報告了Apache?Log4j2遠(yuǎn)程代碼執(zhí)行漏洞(CVE-2021-44228),本文給大家介紹Apache?log4j2-RCE?漏洞復(fù)現(xiàn)(CVE-2021-44228)的相關(guān)知識,感興趣的朋友一起看看吧
    2021-12-12

最新評論

金湖县| 神农架林区| 库尔勒市| 达拉特旗| 凤翔县| 余庆县| 龙井市| 呼和浩特市| 徐汇区| 渭南市| 观塘区| 武冈市| 荔波县| 巴马| 宜春市| 麻江县| 湘西| 齐齐哈尔市| 富顺县| 临湘市| 新田县| 蓬安县| 庆云县| 会同县| 星子县| 庐江县| 黑山县| 西贡区| 贡觉县| 桃江县| 曲阜市| 泰安市| 绥芬河市| 图们市| 赣榆县| 东乌| 遵化市| 南丹县| 黄冈市| 昌宁县| 邵武市|