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

springboot security自定義認(rèn)證過程

 更新時間:2025年03月31日 16:39:17   作者:不識君的荒漠  
這篇文章主要介紹了springboot security自定義認(rèn)證過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

前言

前置閱讀

說明

實際場景,我們一般是把用戶信息保存在db中(也可能是調(diào)用三方接口),需要自定義用戶信息加載或認(rèn)證部分的邏輯。

下面提供一個示例

代碼示例

定義用戶bean

@AllArgsConstructor
@Data
public class User {

    private String username;

    private String password;
}

定義Mapper

示例,代碼寫死了,并不是實際從數(shù)據(jù)庫或某個存儲查詢用戶信息:

@Component
public class UserMapper {

   public User select(String username) {
        return new User(username, "pass");
    }
}

定義加載用戶數(shù)據(jù)的類

UserDetailsService 是spring security內(nèi)置的加載用戶信息的接口,我們只需要實現(xiàn)這個接口:

@Slf4j
@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    public static final UserDetails INVALID_USER =
            new org.springframework.security.core.userdetails.User("invalid_user", "invalid_password", Collections.emptyList());

    private final UserMapper userMapper;

    public UserDetailsServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 根據(jù)用戶名從數(shù)據(jù)庫查詢用戶信息
        User user = userMapper.select(username);
        if (user == null) {
            /**
             * 如果沒查詢到這個用戶,考慮兩種選擇:
             * 1. 返回一個標(biāo)記無效用戶的常量對象
             * 2. 返回一個不可能認(rèn)證通過的用戶
             */
            return INVALID_USER;
//            return new User(username, System.currentTimeMillis() + UUID.randomUUID().toString(), Collections.emptyList());
        }
        /**
         * 這里返回的用戶密碼是否為庫里保存的密碼,是明文/密文,取決于認(rèn)證時密碼比對部分的實現(xiàn),每個人的場景不一樣,
         * 因為使用的是不加密的PasswordEncoder,所以可以返回明文
         */
        return new org.springframework.security.core.userdetails.User(username, user.getPassword(), Collections.emptyList());
    }
}

自定義認(rèn)證的bean配置

@Configuration
public class WebConfiguration {

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 示例,不對密碼進(jìn)行加密處理
        return NoOpPasswordEncoder.getInstance();
    }


    @Bean
    public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        // 設(shè)置加載用戶信息的類
        provider.setUserDetailsService(userDetailsService);
        // 比較用戶密碼的時候,密碼加密方式
        provider.setPasswordEncoder(passwordEncoder);
        return new ProviderManager(Arrays.asList(provider));
    }

}

注意:

  • 因為這個是示例,AuthenticationProvider使用的是spring security的DaoAuthenticationProvider 
  • 在實際場景中,如果不滿足可以自定義實現(xiàn)或者繼承DaoAuthenticationProvider 

重寫其中的:

additionalAuthenticationChecks方法,主要就是認(rèn)證檢查的,默認(rèn)實現(xiàn)如下:

	@Override
	@SuppressWarnings("deprecation")
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
		if (authentication.getCredentials() == null) {
			this.logger.debug("Failed to authenticate since no credentials provided");
			throw new BadCredentialsException(this.messages
					.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
		}
		String presentedPassword = authentication.getCredentials().toString();
		// 就是比對下請求傳過來的密碼和根據(jù)該用戶查詢的密碼是否一致,passwordEncoder是根據(jù)不同的加密算法進(jìn)行加密,示例我們用的是NoOpPasswordEncoder,也就是原始明文比對
		if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
			this.logger.debug("Failed to authenticate since password does not match stored value");
			throw new BadCredentialsException(this.messages
					.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
		}
	}

定義登錄接口

@RequestMapping("/login")
@RestController
public class LoginController {

    private final AuthenticationManager authenticationManager;

    public LoginController(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @PostMapping()
    public Object login(@RequestBody User user) {
        try {
            // 使用定義的AuthenticationManager進(jìn)行認(rèn)證處理
            Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
            // 認(rèn)證通過,設(shè)置到當(dāng)前上下文,如果當(dāng)前認(rèn)證過程后續(xù)還有處理的邏輯需要的話。這個示例是沒有必要了
            SecurityContextHolder.getContext().setAuthentication(authenticate);
            return "login success";
        }catch (Exception e) {
            return "login failed";
        }
    }

    /**
     * 獲取驗證碼,需要的話,可以提供一個驗證碼獲取的接口,在上面的login里把驗證碼傳進(jìn)來進(jìn)行比對
     */
    @GetMapping("/captcha")
    public Object captcha() {
        return "1234";
    }
}

自定義HttpSecurity

@Component
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 在這里自定義配置
        http.authorizeRequests()
                // 登錄相關(guān)接口都允許訪問
                .antMatchers("/login/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .exceptionHandling()
                // 認(rèn)證失敗返回401狀態(tài)碼,前端頁面可以根據(jù)401狀態(tài)碼跳轉(zhuǎn)到登錄頁面
                .authenticationEntryPoint((request, response, authException) ->
                        response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase()))
                .and().cors()
                // csrf是否決定禁用,請自行考量
                .and().csrf().disable()
                // 采用http 的基本認(rèn)證.
                .httpBasic();
    }
}

測試

示例中,用戶密碼寫死是:pass,

  • 用一個錯誤的密碼試一下,響應(yīng)登錄失?。?/li>

  • 使用正確的密碼,響應(yīng)登錄成功:

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring的@Lazy懶加載注解用法詳細(xì)解析

    Spring的@Lazy懶加載注解用法詳細(xì)解析

    這篇文章主要介紹了Spring的@Lazy懶加載注解用法詳細(xì)解析,SpringIoC容器會在啟動的時候?qū)嵗袉螌嵗?nbsp;bean ,如果我們想要實現(xiàn) Spring 在啟動的時候延遲加載 bean,即在首次調(diào)用bean的時候再去執(zhí)行初始化,就可以使用 @Lazy 注解來解決這個問題,需要的朋友可以參考下
    2023-11-11
  • 一篇文章讓你徹底了解Java可重入鎖和不可重入鎖

    一篇文章讓你徹底了解Java可重入鎖和不可重入鎖

    最近正在閱讀Java ReentrantLock源碼,始終對可重入和不可重入概念理解不透徹,今天特地整理了本篇文章,讓你徹底了解Java可重入鎖和不可重入鎖,需要的朋友可以參考下
    2021-06-06
  • SpringCloud Gateway的基本入門和注意點詳解

    SpringCloud Gateway的基本入門和注意點詳解

    這篇文章主要介紹了SpringCloud Gateway的基本入門和注意點,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 如何在Java中使用支付寶SDK來獲取用戶的OpenID

    如何在Java中使用支付寶SDK來獲取用戶的OpenID

    在支付寶開放平臺中,獲取用戶的OpenID通常是在用戶授權(quán)后通過支付寶的OAuth 2.0授權(quán)流程實現(xiàn)的,以下是一個基本的步驟說明,以及如何在Java中使用支付寶SDK來獲取用戶的OpenID
    2024-08-08
  • Java使用continue語句的實例詳解

    Java使用continue語句的實例詳解

    這篇文章主要介紹了Java使用continue語句的實例詳解的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握使用方法,需要的朋友可以參考下
    2017-10-10
  • Java中實現(xiàn)接口與繼承的區(qū)別及說明

    Java中實現(xiàn)接口與繼承的區(qū)別及說明

    這篇文章主要介紹了Java中實現(xiàn)接口與繼承的區(qū)別及說明,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • mybatis insert 返回自增主鍵的實現(xiàn)示例

    mybatis insert 返回自增主鍵的實現(xiàn)示例

    mybatis 在新增之后怎么也獲取不到自增主鍵,本文主要介紹了mybatis insert 返回自增主鍵的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06
  • RabbitMQ的核心原理場景解析及具體應(yīng)用

    RabbitMQ的核心原理場景解析及具體應(yīng)用

    RabbitMQ是基于AMQP的開源消息中間件,通過靈活路由、可靠性保障和高可用特性,實現(xiàn)服務(wù)解耦、流量緩沖及異步通信,本文梳理RabbitMQ 的核心知識,并結(jié)合實戰(zhàn)場景解析其在項目中的具體應(yīng)用,感興趣的朋友一起看看吧
    2025-08-08
  • Springboot實現(xiàn)高吞吐量異步處理詳解(適用于高并發(fā)場景)

    Springboot實現(xiàn)高吞吐量異步處理詳解(適用于高并發(fā)場景)

    這篇文章主要介紹了Springboot實現(xiàn)高吞吐量異步處理詳解(適用于高并發(fā)場景),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • SpringBoot實現(xiàn)短信驗證碼校驗方法思路詳解

    SpringBoot實現(xiàn)短信驗證碼校驗方法思路詳解

    最近做項目遇到這樣的需求,前端是基于BootStrap,html代碼中有BootStrap樣式實現(xiàn)的,具體后臺實現(xiàn)代碼大家通過本文一起學(xué)習(xí)吧
    2017-08-08

最新評論

华安县| 阿拉善右旗| 五常市| 玉龙| 彩票| 满城县| 石狮市| 元江| 宁夏| 灌云县| 石城县| 金门县| 阿克苏市| 沽源县| 玉树县| 凤凰县| 双辽市| 惠东县| 三门县| 习水县| 鄢陵县| 和顺县| 夹江县| 高要市| 黄陵县| 海原县| 喀什市| 扬州市| 岑溪市| 定日县| 深水埗区| 桦南县| 宁夏| 青冈县| 定安县| 山阳县| 边坝县| 昆山市| 武川县| 七台河市| 安岳县|