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

spring boot security自定義認(rèn)證的代碼示例

 更新時(shí)間:2023年07月05日 09:30:26   作者:不識(shí)君的荒漠  
這篇文章主要介紹了spring boot security自定義認(rèn)證,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

前言

前置閱讀

spring boot security快速使用示例

SpringBoot+Vue前后端分離,使用SpringSecurity完美處理權(quán)限問(wèn)題的解決方法

說(shuō)明

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

代碼示例

定義用戶bean

@AllArgsConstructor
@Data
public class User {
    private String username;
    private String password;
}

定義Mapper

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

@Component
public class UserMapper {
   public User select(String username) {
        return new User(username, "pass");
    }
}

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

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

@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ù)庫(kù)查詢用戶信息
        User user = userMapper.select(username);
        if (user == null) {
            /**
             * 如果沒(méi)查詢到這個(gè)用戶,考慮兩種選擇:
             * 1. 返回一個(gè)標(biāo)記無(wú)效用戶的常量對(duì)象
             * 2. 返回一個(gè)不可能認(rèn)證通過(guò)的用戶
             */
            return INVALID_USER;
//            return new User(username, System.currentTimeMillis() + UUID.randomUUID().toString(), Collections.emptyList());
        }
        /**
         * 這里返回的用戶密碼是否為庫(kù)里保存的密碼,是明文/密文,取決于認(rèn)證時(shí)密碼比對(duì)部分的實(shí)現(xiàn),每個(gè)人的場(chǎng)景不一樣,
         * 因?yàn)槭褂玫氖遣患用艿腜asswordEncoder,所以可以返回明文
         */
        return new org.springframework.security.core.userdetails.User(username, user.getPassword(), Collections.emptyList());
    }
}

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

@Configuration
public class WebConfiguration {
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 示例,不對(duì)密碼進(jìn)行加密處理
        return NoOpPasswordEncoder.getInstance();
    }
    @Bean
    public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        // 設(shè)置加載用戶信息的類
        provider.setUserDetailsService(userDetailsService);
        // 比較用戶密碼的時(shí)候,密碼加密方式
        provider.setPasswordEncoder(passwordEncoder);
        return new ProviderManager(Arrays.asList(provider));
    }
}

注意,因?yàn)檫@個(gè)是示例,AuthenticationProvider使用的是spring security的DaoAuthenticationProvider ,在實(shí)際場(chǎng)景中,如果不滿足可以自定義實(shí)現(xiàn)或者繼承DaoAuthenticationProvider ,重寫其中的:additionalAuthenticationChecks方法,主要就是認(rèn)證檢查的,默認(rèn)實(shí)現(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();
		// 就是比對(duì)下請(qǐng)求傳過(guò)來(lái)的密碼和根據(jù)該用戶查詢的密碼是否一致,passwordEncoder是根據(jù)不同的加密算法進(jìn)行加密,示例我們用的是NoOpPasswordEncoder,也就是原始明文比對(duì)
		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)證通過(guò),設(shè)置到當(dāng)前上下文,如果當(dāng)前認(rèn)證過(guò)程后續(xù)還有處理的邏輯需要的話。這個(gè)示例是沒(méi)有必要了
            SecurityContextHolder.getContext().setAuthentication(authenticate);
            return "login success";
        }catch (Exception e) {
            return "login failed";
        }
    }
    /**
     * 獲取驗(yàn)證碼,需要的話,可以提供一個(gè)驗(yàn)證碼獲取的接口,在上面的login里把驗(yàn)證碼傳進(jìn)來(lái)進(jìn)行比對(duì)
     */
    @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)接口都允許訪問(wèn)
                .antMatchers("/login/**").permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .exceptionHandling()
                // 認(rèn)證失敗返回401狀態(tài)碼,前端頁(yè)面可以根據(jù)401狀態(tài)碼跳轉(zhuǎn)到登錄頁(yè)面
                .authenticationEntryPoint((request, response, authException) ->
                        response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase()))
                .and().cors()
                // csrf是否決定禁用,請(qǐng)自行考量
                .and().csrf().disable()
                // 采用http 的基本認(rèn)證.
                .httpBasic();
    }
}

測(cè)試

示例中,用戶密碼寫死是:pass,用一個(gè)錯(cuò)誤的密碼試一下,響應(yīng)登錄失敗:

在這里插入圖片描述

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

在這里插入圖片描述

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

相關(guān)文章

  • windows下 jdk1.7安裝教程圖解

    windows下 jdk1.7安裝教程圖解

    java編程的初學(xué)者在開始編碼前都會(huì)遇到一個(gè)難題,那就是jdk1.7環(huán)境變量配置怎么操作,怎么安裝,針對(duì)這個(gè)難題,小編特地為大家整理相關(guān)教程,不了解的朋友可以前往查看使用
    2018-05-05
  • idea 多模塊項(xiàng)目依賴父工程class找不到問(wèn)題的方法

    idea 多模塊項(xiàng)目依賴父工程class找不到問(wèn)題的方法

    這篇文章主要介紹了idea 多模塊項(xiàng)目依賴父工程class找不到問(wèn)題的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-01-01
  • java迭代子模式詳解

    java迭代子模式詳解

    這篇文章主要為大家詳細(xì)介紹了java迭代子模式的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • Java?獲取Zookeeper節(jié)點(diǎn)下所有數(shù)據(jù)詳細(xì)步驟

    Java?獲取Zookeeper節(jié)點(diǎn)下所有數(shù)據(jù)詳細(xì)步驟

    本文介紹了如何使用Java獲取ZooKeeper節(jié)點(diǎn)下所有數(shù)據(jù),實(shí)際應(yīng)用示例中,我們演示了如何從ZooKeeper節(jié)點(diǎn)下獲取配置信息并輸出到控制臺(tái),ZooKeeper是一個(gè)開源的分布式協(xié)調(diào)服務(wù),適用于分布式系統(tǒng)中的數(shù)據(jù)同步、配置管理、命名服務(wù)等功能,感興趣的朋友一起看看吧
    2024-11-11
  • idea啟動(dòng)Tomcat時(shí)控制臺(tái)亂碼的解決方法(親測(cè)有效)

    idea啟動(dòng)Tomcat時(shí)控制臺(tái)亂碼的解決方法(親測(cè)有效)

    最近在idea中啟動(dòng)tomcat出現(xiàn)控制臺(tái)亂碼問(wèn)題,嘗試了很多方法,最后終于解決了,所以下面這篇文章主要給大家介紹了關(guān)于idea啟動(dòng)Tomcat時(shí)控制臺(tái)亂碼的解決方法,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • springboot vue完成編輯頁(yè)面發(fā)送接口請(qǐng)求功能

    springboot vue完成編輯頁(yè)面發(fā)送接口請(qǐng)求功能

    這篇文章主要為大家介紹了springboot+vue完成編輯頁(yè)發(fā)送接口請(qǐng)求功能,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • 一文帶你了解Java中的SPI機(jī)制

    一文帶你了解Java中的SPI機(jī)制

    SPI 全稱是 Service Provider Interface,是一種 JDK 內(nèi)置的動(dòng)態(tài)加載實(shí)現(xiàn)擴(kuò)展點(diǎn)的機(jī)制,本文主要為大家介紹了SPI機(jī)制的原理與使用,需要的可以參考一下
    2023-04-04
  • 詳解Java的引用類型及使用場(chǎng)景

    詳解Java的引用類型及使用場(chǎng)景

    這篇文章主要介紹了詳解Java的引用類型及使用場(chǎng)景,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-03-03
  • Java基礎(chǔ)高級(jí)綜合練習(xí)題撲克牌的創(chuàng)建

    Java基礎(chǔ)高級(jí)綜合練習(xí)題撲克牌的創(chuàng)建

    今天小編就為大家分享一篇關(guān)于Java基礎(chǔ)高級(jí)綜合練習(xí)題撲克牌的創(chuàng)建,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Java設(shè)計(jì)模式之策略模式詳解

    Java設(shè)計(jì)模式之策略模式詳解

    這篇文章主要為大家詳細(xì)介紹了Java設(shè)計(jì)模式之策略模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評(píng)論

东源县| 军事| 上饶市| 新疆| 天峻县| 巴青县| 漾濞| 灵丘县| 宝应县| 武冈市| 新建县| 红河县| 金乡县| 沙洋县| 新泰市| 贵溪市| 浦北县| 黄石市| 离岛区| 柘荣县| 雷波县| 房产| 红桥区| 武汉市| 久治县| 仁布县| 乡城县| 石柱| 江津市| 营山县| 哈密市| 孝义市| 永福县| 微山县| 普安县| 迁安市| 辽阳市| 阿鲁科尔沁旗| 东乌珠穆沁旗| 钦州市| 绥宁县|