欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

Authentication

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

我們實(shí)現(xiàn)這個(gè)類可以了,他已經(jīng)實(shí)現(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;
    }
}

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

AuthenticationProvider

接著是AuthenticationProvider,需要實(shí)現(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)入配置了

通常都會(huì)有一個(gè)實(shí)現(xiàn)了WebSecurityConfigurerAdapter的配置類

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

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

UserDetailsService

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

這個(gè)類就非常熟悉了,只需要實(shí)現(xiàn)他的loadUserByUsername方法,就可以實(shí)現(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
//這個(gè)參數(shù)不為空,就表明認(rèn)證通過,所以空集合也可以通過
        return new User(spliceStaffInfo,account.getPassword(), AuthorityUtils.NO_AUTHORITIES);
    }

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

TokenFilter

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

@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);
}

登錄過程

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

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

//通過 AuthenticationManager(默認(rèn)實(shí)現(xiàn)為ProviderManager)的authenticate方法驗(yàn)證 Authentication 對(duì)象 
//AuthenticationManager會(huì)通過你傳入的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);

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

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

相關(guān)文章

  • springboot使用yml文件配置多環(huán)境方式(dev、test、prod)

    springboot使用yml文件配置多環(huán)境方式(dev、test、prod)

    這篇文章主要介紹了springboot使用yml文件配置多環(huán)境方式(dev、test、prod),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Spring-Boot 集成Solr客戶端的詳細(xì)步驟

    Spring-Boot 集成Solr客戶端的詳細(xì)步驟

    本篇文章主要介紹了Spring-Boot 集成Solr客戶端的詳細(xì)步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-11-11
  • spring boot 自動(dòng)更新靜態(tài)文件和后臺(tái)代碼的實(shí)例

    spring boot 自動(dòng)更新靜態(tài)文件和后臺(tái)代碼的實(shí)例

    下面小編就為大家分享一篇spring boot 自動(dòng)更新靜態(tài)文件和后臺(tái)代碼的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • Java Lambda表達(dá)式之從集合到流

    Java Lambda表達(dá)式之從集合到流

    這篇文章主要介紹了Java Lambda表達(dá)式之從集合到流知識(shí),非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • Java源碼難點(diǎn)突破Lambda表達(dá)式執(zhí)行原理

    Java源碼難點(diǎn)突破Lambda表達(dá)式執(zhí)行原理

    這篇文章主要為大家介紹了Java難點(diǎn)突破Lambda表達(dá)式執(zhí)行原理分析及示例的實(shí)現(xiàn)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • FactoryBean?BeanFactory方法使用示例詳解講解

    FactoryBean?BeanFactory方法使用示例詳解講解

    這篇文章主要為大家介紹了FactoryBean?BeanFactory方法使用示例詳解講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • 使用java數(shù)組 封裝自己的數(shù)組操作示例

    使用java數(shù)組 封裝自己的數(shù)組操作示例

    這篇文章主要介紹了使用java數(shù)組 封裝自己的數(shù)組操作,結(jié)合實(shí)例形式分析了java數(shù)組索引、遍歷等相關(guān)封裝操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2020-03-03
  • Spring Boot框架中的@Conditional注解示例詳解

    Spring Boot框架中的@Conditional注解示例詳解

    這篇文章主要介紹了Spring Boot框架中的@Conditional系列注解,@ConditionalOnProperty注解的作用是解析application.yml/application.properties 里的配置生成條件來生效,也是與@Configuration注解一起使用,本文通過示例代碼給大家介紹的非常詳細(xì),需要的朋友一起看看吧
    2022-09-09
  • Spring中ApplicationContextAware的使用方法詳解

    Spring中ApplicationContextAware的使用方法詳解

    ApplicationContextAware?通過它Spring容器會(huì)自動(dòng)把上下文環(huán)境對(duì)象調(diào)用ApplicationContextAware接口中的setApplicationContext方法,這篇文章主要介紹了Spring中ApplicationContextAware的作用,需要的朋友可以參考下
    2023-03-03
  • spring之SpEL表達(dá)式詳解

    spring之SpEL表達(dá)式詳解

    這篇文章主要介紹了spring之SpEL表達(dá)式詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評(píng)論