国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

spring boot security使用jwt認(rèn)證

這篇具有很好參考價值的文章主要介紹了spring boot security使用jwt認(rèn)證。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

前言

在前面的幾篇文章中:
spring boot security快速使用示例
spring boot security之前后端分離配置
spring boot security自定義認(rèn)證
spring boot security驗(yàn)證碼登錄示例
基本對常用的基于cookie和session的認(rèn)證使用場景都已覆蓋。但是session屬于有狀態(tài)認(rèn)證,本文給出一個無狀態(tài)的認(rèn)證:jwt認(rèn)證示例。

代碼示例

下面會提供完整的示例代碼:

依賴

使用的spring boot 2.6.11版本,jdk8。

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.20</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>com.github.penggle</groupId>
			<artifactId>kaptcha</artifactId>
			<version>2.3.2</version>
		</dependency>

		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.9.1</version>
		</dependency>

定義mapper

定義一個查詢用戶信息的接口:文章來源地址http://www.zghlxwxcb.cn/news/detail-522988.html

@Component
public class UserMapper {

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

定義用戶信息的實(shí)體bean

@Data
public class User {

    private String username;

    private String password;

    private String captcha;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public User(String username, String password, String captcha) {
        this.username = username;
        this.password = password;
        this.captcha = captcha;
    }
}

security相關(guān)的類

  1. 實(shí)現(xiàn)spring security內(nèi)置的UserDetailsService接口,根據(jù)用戶名返回用戶信息:
@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)證時密碼比對部分的實(shí)現(xiàn),每個人的場景不一樣,
         * 因?yàn)槭褂玫氖遣患用艿腜asswordEncoder,所以可以返回明文
         */
        return new org.springframework.security.core.userdetails.User(username, user.getPassword(), Collections.emptyList());
    }
}
  1. 定義jwt工具類
public class JwtUtil {

    public static final String SECRET = TextCodec.BASE64.encode("secret");

    public static final long EXPIRE_SECONDS = 3600L;

    /**
     * 從token中解析出用戶名
     */
    public static String getUsernameFromToken(String token) {
        return getClaimFromToken(token, Claims::getSubject);
    }

    /**
     * 從token中獲取過期時間
     */
    public static Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getExpiration);
    }

    /**
     * 解析出token聲明.
     */
    public static <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        return claimsResolver.apply(claims);
    }

    /**
     * token是否過期
     */
    public static Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    /**
     * 生成token
     */
    public static String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, userDetails.getUsername());
    }

    /**
     * token是否合法.
     */
    public static Boolean isValidateToken(String token, UserDetails userDetails) {
        final String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }

    private static String doGenerateToken(Map<String, Object> claims, String subject) {
        return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE_SECONDS * 1000))
                .signWith(SignatureAlgorithm.HS512, SECRET).compact();
    }

}

  1. 定義jwt認(rèn)證的過濾器
@Slf4j
@Component
public class JwtRequestFilter extends OncePerRequestFilter {


    private final UserDetailsService userDetailsService;


    public JwtRequestFilter(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

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

        final String requestTokenHeader = request.getHeader(HttpHeaders.AUTHORIZATION);

        String username = null;
        String jwtToken = null;
        if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
            jwtToken = requestTokenHeader.substring(7);
            try {
                username = JwtUtil.getUsernameFromToken(jwtToken);
            } catch (Exception e) {
                log.error("獲取token失敗: {}, {}", jwtToken, e.getMessage());
            }
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            // 根據(jù)用戶名加載用戶信息
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            // 判斷token是否有效
            if (JwtUtil.isValidateToken(jwtToken, userDetails)) {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request, response);
    }

}

  1. 注冊相關(guān)bean到spring容器
@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));
    }
    
    @Bean
    public Producer defaultKaptcha() {
        Properties properties = new Properties();
        // 還有一些其它屬性,可以進(jìn)行源碼自己看相關(guān)配置,比較清楚了,根據(jù)變量名也能猜出來什么意思了
        properties.setProperty(Constants.KAPTCHA_IMAGE_WIDTH, "150");
        properties.setProperty(Constants.KAPTCHA_IMAGE_HEIGHT, "50");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, "0123456789abcdefghigklmnopqrstuvwxyz");
        properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }

}
  1. 自定義 WebSecurityConfigurer
@Component
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    private final JwtRequestFilter jwtRequestFilter;

    public WebSecurityConfigurer(JwtRequestFilter jwtRequestFilter) {
        this.jwtRequestFilter = jwtRequestFilter;
    }

    @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()
                // 設(shè)置session是無關(guān)的
                .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

    }
}

提供登錄接口

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

    private final AuthenticationManager authenticationManager;

    private final Producer producer;

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

    @PostMapping()
    public Object login(@RequestBody User user, HttpSession session) {
        Object captcha = session.getAttribute(Constants.KAPTCHA_SESSION_KEY);
        if (captcha == null || !captcha.toString().equalsIgnoreCase(user.getCaptcha())) {
            return "captcha is not correct.";
        }
        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);
            String token = JwtUtil.generateToken((UserDetails) authenticate.getPrincipal());
            return token;
        } catch (Exception e) {
            return "login failed";
        }
    }

    /**
     * 獲取驗(yàn)證碼,需要的話,可以提供一個驗(yàn)證碼獲取的接口,在上面的login里把驗(yàn)證碼傳進(jìn)來進(jìn)行比對
     */
    @GetMapping("/captcha")
    public void captcha(HttpServletResponse response, HttpSession session) throws IOException {
        response.setContentType("image/jpeg");
        String text = producer.createText();
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, text);
        BufferedImage image = producer.createImage(text);
        try (ServletOutputStream out = response.getOutputStream()) {
            ImageIO.write(image, "jpg", out);
        }
    }
}

測試

提供一個用于測試的接口

@RequestMapping("/hello")
@RestController
public class HelloController {

    @GetMapping("/world")
    public Object helloWorld() {
        return "hello, world";
    }
}

驗(yàn)證

  1. 獲取驗(yàn)證碼
    spring boot security使用jwt認(rèn)證,spring全家桶,spring boot,后端,security,jwt
  2. 登錄
    spring boot security使用jwt認(rèn)證,spring全家桶,spring boot,后端,security,jwt
  3. 使用登錄的token訪問接口
    spring boot security使用jwt認(rèn)證,spring全家桶,spring boot,后端,security,jwt
  4. 如果沒有token或不正確是訪問受限的
    spring boot security使用jwt認(rèn)證,spring全家桶,spring boot,后端,security,jwt

到了這里,關(guān)于spring boot security使用jwt認(rèn)證的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • SpringBoot2.3集成Spring Security(二) JWT認(rèn)證

    SpringBoot2.3集成Spring Security(二) JWT認(rèn)證

    緊接上文,我們已經(jīng)完成了 SpringBoot中集成Spring Security,并且用戶名帳號和密碼都是從數(shù)據(jù)庫中獲取。但是這種方式還是不能滿足現(xiàn)在的開發(fā)需求。 使用JWT的好處: 無狀態(tài)認(rèn)證:JWT本身包含了認(rèn)證信息和聲明,服務(wù)器不需要在會話中保存任何狀態(tài)。這樣使得應(yīng)用程序可以更加

    2024年02月11日
    瀏覽(21)
  • Spring Boot 優(yōu)雅集成 Spring Security 5.7(安全框架)與 JWT(雙令牌機(jī)制)

    Spring Boot 優(yōu)雅集成 Spring Security 5.7(安全框架)與 JWT(雙令牌機(jī)制)

    本章節(jié)將介紹 Spring Boot 集成 Spring Security 5.7(安全框架)。 ?? Spring Boot 2.x 實(shí)踐案例(代碼倉庫) Spring Security 是一個能夠?yàn)榛?Spring 的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。 它提供了一組可以在 Spring 應(yīng)用上下文中配置的 Bean,充分利用了 Spring

    2024年02月12日
    瀏覽(53)
  • 后端進(jìn)階之路——綜述Spring Security認(rèn)證,授權(quán)(一)

    后端進(jìn)階之路——綜述Spring Security認(rèn)證,授權(quán)(一)

    「作者主頁」 :雪碧有白泡泡 「個人網(wǎng)站」 :雪碧的個人網(wǎng)站 「推薦專欄」 : ★ java一站式服務(wù) ★ ★ 前端炫酷代碼分享 ★ ★ uniapp-從構(gòu)建到提升 ★ ★ 從0到英雄,vue成神之路 ★ ★ 解決算法,一個專欄就夠了 ★ ★ 架構(gòu)咱們從0說 ★ ★ 數(shù)據(jù)流通的精妙之道★ ★后端進(jìn)

    2024年02月14日
    瀏覽(21)
  • 使用Spring Boot Security 實(shí)現(xiàn)多認(rèn)證 手機(jī)號登錄 微信掃碼登錄 微信掃碼注冊

    使用Spring Boot Security 實(shí)現(xiàn)多認(rèn)證 手機(jī)號登錄 微信掃碼登錄 微信掃碼注冊

    Spring Boot 3.x Spring Security 5.7 Spring Redis MyBatis plus 前端 Vue 公司 最近有個新項(xiàng)目 使用單點(diǎn)登錄 sso 百度了一圈 也沒怎么找到微信掃碼注冊的功能于是自己寫 需求就是 手機(jī) + 密碼登錄 微信掃碼登錄 微信掃碼注冊 微信二維碼 登錄 和注冊二合一 具體實(shí)現(xiàn) 稍后我會說 本教程將指導(dǎo)

    2024年04月10日
    瀏覽(25)
  • Spring Boot 3 + JWT + Security 聯(lián)手打造安全帝國:一篇文章讓你掌握未來!

    Spring Boot 3 + JWT + Security 聯(lián)手打造安全帝國:一篇文章讓你掌握未來!

    Spring Security 已經(jīng)成為 java 后臺權(quán)限校驗(yàn)的第一選擇.今天就通過讀代碼的方式帶大家深入了解一下Security,本文主要是基于開源項(xiàng)目spring-boot-3-jwt-security來講解Spring Security + JWT(Json Web Token).實(shí)現(xiàn)用戶鑒權(quán),以及權(quán)限校驗(yàn). 所有代碼基于 jdk17+ 構(gòu)建.現(xiàn)在讓我們開始吧! Springboot 3.0 Spri

    2024年02月07日
    瀏覽(89)
  • Spring Boot Security認(rèn)證:Redis緩存用戶信息

    Spring Boot Security認(rèn)證:Redis緩存用戶信息

    ??歡迎來到架構(gòu)設(shè)計(jì)專欄~Spring Boot Security認(rèn)證:Redis緩存用戶信息 ☆* o(≧▽≦)o *☆嗨~我是IT·陳寒?? ?博客主頁:IT·陳寒的博客 ??該系列文章專欄:架構(gòu)設(shè)計(jì) ??其他專欄:Java學(xué)習(xí)路線 Java面試技巧 Java實(shí)戰(zhàn)項(xiàng)目 AIGC人工智能 數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí) ??文章作者技術(shù)和水平有限,如

    2024年02月04日
    瀏覽(21)
  • Spring Boot 整合SpringSecurity和JWT和Redis實(shí)現(xiàn)統(tǒng)一鑒權(quán)認(rèn)證

    Spring Boot 整合SpringSecurity和JWT和Redis實(shí)現(xiàn)統(tǒng)一鑒權(quán)認(rèn)證

    本文主要講了Spring Security文章,如果有什么需要改進(jìn)的地方還請大佬指出?? ??作者簡介:大家好,我是青衿?? ??博客首頁:CSDN主頁放風(fēng)講故事 ??每日一句:努力一點(diǎn),優(yōu)秀一點(diǎn) Spring Security Spring Security是一個強(qiáng)大且高度可定制的身份驗(yàn)證和訪問控制框架。它是保護(hù)基

    2024年02月05日
    瀏覽(21)
  • Spring Boot + Vue的網(wǎng)上商城之springsecurity+jwt+redis實(shí)現(xiàn)用戶權(quán)限認(rèn)證實(shí)現(xiàn)

    在網(wǎng)上商城項(xiàng)目中,用戶的安全性是非常重要的。為了實(shí)現(xiàn)用戶權(quán)限認(rèn)證和安全校驗(yàn),我們可以使用Spring Security、JWT和Redis來實(shí)現(xiàn)。本篇博客將詳細(xì)介紹后端和前臺的實(shí)現(xiàn)過程,并提供相應(yīng)的代碼案例。 當(dāng)用戶點(diǎn)擊登錄按鈕時,前端發(fā)送一個POST請求到后端的登錄接口,傳遞用

    2024年02月07日
    瀏覽(22)
  • Spring Authorization Server入門 (八) Spring Boot引入Security OAuth2 Client對接認(rèn)證服務(wù)

    Spring Authorization Server入門 (八) Spring Boot引入Security OAuth2 Client對接認(rèn)證服務(wù)

    在之前的文章中實(shí)現(xiàn)了一個認(rèn)證服務(wù),并且添加了一些自定義的內(nèi)容,現(xiàn)在暫時沒想到認(rèn)證服務(wù)的新內(nèi)容,本篇文章就先寫一下客戶端對接的吧,水一篇。 當(dāng)用戶通過客戶端去訪問一個受限的資源時,客戶端會檢測是否有登錄信息,沒有登錄信息會重定向至認(rèn)證服務(wù)器去請求

    2024年02月21日
    瀏覽(28)
  • Spring Gateway使用JWT實(shí)現(xiàn)統(tǒng)一身份認(rèn)證

    Spring Gateway使用JWT實(shí)現(xiàn)統(tǒng)一身份認(rèn)證

    在開發(fā)集群式或分布式服務(wù)時,鑒權(quán)是最重要的一步,為了方便對請求統(tǒng)一鑒權(quán),一般都是會放在網(wǎng)關(guān)中進(jìn)行處理。目前非常流行的一種方案是使用JWT,詳細(xì)的使用說明,可以找相關(guān)的資料查閱,這里先不進(jìn)行深入的引用了。主要使用它下面的特性: 它的數(shù)據(jù)使用JSON格式封

    2024年02月12日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包