日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解

瀏覽:23日期:2023-03-25 14:16:11
1 簡介

Spring Security作為成熟且強(qiáng)大的安全框架,得到許多大廠的青睞。而作為前后端分離的SSO方案,JWT也在許多項(xiàng)目中應(yīng)用。本文將介紹如何通過Spring Security實(shí)現(xiàn)JWT認(rèn)證。

用戶與服務(wù)器交互大概如下:

Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解

客戶端獲取JWT,一般通過POST方法把用戶名/密碼傳給server; 服務(wù)端接收到客戶端的請求后,會檢驗(yàn)用戶名/密碼是否正確,如果正確則生成JWT并返回;不正確則返回錯誤; 客戶端拿到JWT后,在有效期內(nèi)都可以通過JWT來訪問資源了,一般把JWT放在請求頭;一次獲取,多次使用; 服務(wù)端校驗(yàn)JWT是否合法,合法則允許客戶端正常訪問,不合法則返回401。 2 項(xiàng)目整合

我們把要整合的Spring Security和JWT加入到項(xiàng)目的依賴中去:

<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>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version></dependency>2.1 JWT整合2.1.1 JWT工具類

JWT工具類起碼要具有以下功能:

根據(jù)用戶信息生成JWT; 校驗(yàn)JWT是否合法,如是否被篡改、是否過期等; 從JWT中解析用戶信息,如用戶名、權(quán)限等;

具體代碼如下:

@Componentpublic class JwtTokenProvider { @Autowired JwtProperties jwtProperties; @Autowired private CustomUserDetailsService userDetailsService; private String secretKey; @PostConstruct protected void init() { secretKey = Base64.getEncoder().encodeToString(jwtProperties.getSecretKey().getBytes()); } public String createToken(String username, List<String> roles) { Claims claims = Jwts.claims().setSubject(username); claims.put('roles', roles); Date now = new Date(); Date validity = new Date(now.getTime() + jwtProperties.getValidityInMs()); return Jwts.builder()// .setClaims(claims)// .setIssuedAt(now)// .setExpiration(validity)// .signWith(SignatureAlgorithm.HS256, secretKey)// .compact(); } public Authentication getAuthentication(String token) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(getUsername(token)); return new UsernamePasswordAuthenticationToken(userDetails, '', userDetails.getAuthorities()); } public String getUsername(String token) { return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject(); } public String resolveToken(HttpServletRequest req) { String bearerToken = req.getHeader('Authorization'); if (bearerToken != null && bearerToken.startsWith('Bearer ')) { return bearerToken.substring(7); } return null; } public boolean validateToken(String token) { try { Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); if (claims.getBody().getExpiration().before(new Date())) { return false; } return true; } catch (JwtException | IllegalArgumentException e) { throw new InvalidJwtAuthenticationException('Expired or invalid JWT token'); } }}

工具類還實(shí)現(xiàn)了另一個功能:從HTTP請求頭中獲取JWT。

2.1.2 Token處理的Filter

Filter是Security處理的關(guān)鍵,基本上都是通過Filter來攔截請求的。首先從請求頭取出JWT,然后校驗(yàn)JWT是否合法,如果合法則取出Authentication保存在SecurityContextHolder里。如果不合法,則做異常處理。

public class JwtTokenAuthenticationFilter extends GenericFilterBean { private JwtTokenProvider jwtTokenProvider; public JwtTokenAuthenticationFilter(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; try { String token = jwtTokenProvider.resolveToken(request); if (token != null && jwtTokenProvider.validateToken(token)) { Authentication auth = jwtTokenProvider.getAuthentication(token); if (auth != null) { SecurityContextHolder.getContext().setAuthentication(auth); } } } catch (InvalidJwtAuthenticationException e) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.getWriter().write('Invalid token'); response.getWriter().flush(); return; } filterChain.doFilter(req, res); }}

對于異常處理,使用@ControllerAdvice是不行的,應(yīng)該這個是Filter,在這里拋的異常還沒有到DispatcherServlet,無法處理。所以Filter要自己做異常處理:

catch (InvalidJwtAuthenticationException e) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); response.getWriter().write('Invalid token'); response.getWriter().flush(); return;}

最后的return不能省略,因?yàn)橐呀?jīng)要把輸出的內(nèi)容給Response了,沒有必要再往后傳遞,否則報錯

java.lang.IllegalStateException: getWriter() has already been called2.1.3 JWT屬性

JWT需要配置一個密鑰來加密,同時還要配置JWT令牌的有效期。

@Configuration@ConfigurationProperties(prefix = 'pkslow.jwt')public class JwtProperties { private String secretKey = 'pkslow.key'; private long validityInMs = 3600_000;//getter and setter}2.2 Spring Security整合

Spring Security的整個框架還是比較復(fù)雜的,簡化后大概如下圖所示:

Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解

它是通過一連串的Filter來進(jìn)行安全管理。細(xì)節(jié)這里先不展開講。

2.2.1 WebSecurityConfigurerAdapter配置

這個配置也可以理解為是FilterChain的配置,可以不用理解,代碼很好懂它做了什么:

@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired JwtTokenProvider jwtTokenProvider; @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } @Override protected void configure(HttpSecurity http) throws Exception { http .httpBasic().disable() .csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers('/auth/login').permitAll() .antMatchers(HttpMethod.GET, '/admin').hasRole('ADMIN') .antMatchers(HttpMethod.GET, '/user').hasRole('USER') .anyRequest().authenticated() .and() .apply(new JwtSecurityConfigurer(jwtTokenProvider)); }}

這里通過HttpSecurity配置了哪些請求需要什么權(quán)限才可以訪問。

/auth/login用于登陸獲取JWT,所以都能訪問; /admin只有ADMIN用戶才可以訪問; /user只有USER用戶才可以訪問。

而之前實(shí)現(xiàn)的Filter則在下面配置使用:

public class JwtSecurityConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> { private JwtTokenProvider jwtTokenProvider; public JwtSecurityConfigurer(JwtTokenProvider jwtTokenProvider) { this.jwtTokenProvider = jwtTokenProvider; } @Override public void configure(HttpSecurity http) throws Exception { JwtTokenAuthenticationFilter customFilter = new JwtTokenAuthenticationFilter(jwtTokenProvider); http.exceptionHandling() .authenticationEntryPoint(new JwtAuthenticationEntryPoint()) .and() .addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); }}2.2.2 用戶從哪來

通常在Spring Security的世界里,都是通過實(shí)現(xiàn)UserDetailsService來獲取UserDetails的。

@Componentpublic class CustomUserDetailsService implements UserDetailsService { private UserRepository users; public CustomUserDetailsService(UserRepository users) { this.users = users; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return this.users.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException('Username: ' + username + ' not found')); }}

對于UserRepository,可以從數(shù)據(jù)庫中讀取,或者其它用戶管理中心。為了方便,我使用Map放了兩個用戶:

@Repositorypublic class UserRepository { private static final Map<String, User> allUsers = new HashMap<>(); @Autowired private PasswordEncoder passwordEncoder; @PostConstruct protected void init() { allUsers.put('pkslow', new User('pkslow', passwordEncoder.encode('123456'), Collections.singletonList('ROLE_ADMIN'))); allUsers.put('user', new User('user', passwordEncoder.encode('123456'), Collections.singletonList('ROLE_USER'))); } public Optional<User> findByUsername(String username) { return Optional.ofNullable(allUsers.get(username)); }}3 測試

完成代碼編寫后,我們來測試一下:

(1)無JWT訪問,失敗

curl http://localhost:8080/admin{'timestamp':'2021-02-06T05:45:06.385+0000','status':403,'error':'Forbidden','message':'Access Denied','path':'/admin'}$ curl http://localhost:8080/user{'timestamp':'2021-02-06T05:45:16.438+0000','status':403,'error':'Forbidden','message':'Access Denied','path':'/user'}

(2)admin獲取JWT,密碼錯誤則失敗,密碼正確則成功

$ curl http://localhost:8080/auth/login -X POST -d ’{'username':'pkslow','password':'xxxxxx'}’ -H ’Content-Type: application/json’{'timestamp':'2021-02-06T05:47:16.254+0000','status':403,'error':'Forbidden','message':'Access Denied','path':'/auth/login'}$ curl http://localhost:8080/auth/login -X POST -d ’{'username':'pkslow','password':'123456'}’ -H ’Content-Type: application/json’eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwa3Nsb3ciLCJyb2xlcyI6WyJST0xFX0FETUlOIl0sImlhdCI6MTYxMjU5MDYxNCwiZXhwIjoxNjEyNTkxMjE0fQ.d4Gi50aaOsHHqpM0d8Mh1960otnZf7rlE3x6xSfakVo

(3)admin帶JWT訪問/admin,成功;訪問/user失敗

$ curl http://localhost:8080/admin -H ’Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwa3Nsb3ciLCJyb2xlcyI6WyJST0xFX0FETUlOIl0sImlhdCI6MTYxMjU5MDYxNCwiZXhwIjoxNjEyNTkxMjE0fQ.d4Gi50aaOsHHqpM0d8Mh1960otnZf7rlE3x6xSfakVo’you are admin$ curl http://localhost:8080/user -H ’Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwa3Nsb3ciLCJyb2xlcyI6WyJST0xFX0FETUlOIl0sImlhdCI6MTYxMjU5MDYxNCwiZXhwIjoxNjEyNTkxMjE0fQ.d4Gi50aaOsHHqpM0d8Mh1960otnZf7rlE3x6xSfakVo’{'timestamp':'2021-02-06T05:51:23.099+0000','status':403,'error':'Forbidden','message':'Forbidden','path':'/user'}

(4)使用過期的JWT訪問,失敗

$ curl http://localhost:8080/admin -H ’Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJwa3Nsb3ciLCJyb2xlcyI6WyJST0xFX0FETUlOIl0sImlhdCI6MTYxMjU5MDQ0OSwiZXhwIjoxNjEyNTkwNTA5fQ.CSaubE4iJcYATbLmbb59aNFU1jNCwDFHUV3zIakPU64’Invalid token4 總結(jié)

代碼請查看:https://github.com/LarryDpk/pkslow-samples

以上就是Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解的詳細(xì)內(nèi)容,更多關(guān)于Springboot集成Spring Security的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Spring
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久久久久自在自线| 亚洲乱码久久| 日本久久一区| 亚洲精品免费观看| 亚洲精品黄色| 欧美日韩亚洲三区| 欧美亚洲免费| 色爱综合网欧美| 91一区二区三区四区| 亚洲精品国产日韩| 日韩国产精品久久久久久亚洲| 亚洲精品高潮| 国产精品调教视频| 国产高潮在线| 欧美不卡视频| 日韩精品视频在线看| 日本免费在线视频不卡一不卡二| 97久久亚洲| 在线看片福利| 美国三级日本三级久久99 | 狂野欧美性猛交xxxx| 亚洲深夜视频| 久久亚洲风情| 国产精品蜜月aⅴ在线| 91精品国产福利在线观看麻豆| 婷婷综合亚洲| 欧美精品影院| 在线日韩电影| 久久精品凹凸全集| 久久久精品久久久久久96 | 精品久久91| 亚洲欧美日韩综合国产aⅴ| 日韩黄色av| 欧美jjzz| 国产一区二区三区黄网站| 亚洲激情欧美| 国产精品久久久久蜜臀 | 精品国产精品久久一区免费式 | 国产高清一区二区| 精品亚洲自拍| 五月激激激综合网色播| 久久精品在线| 精品久久美女| 国产精品成人3p一区二区三区| 欧美特黄视频| 精品五月天堂| 91精品啪在线观看国产爱臀| 亚洲视频播放| 久久精品播放| 国产福利电影在线播放| 四虎成人av| 九九99久久精品在免费线bt| 天堂成人国产精品一区| 天堂av一区| 日本精品在线中文字幕| 亚洲网站视频| 麻豆一区二区99久久久久| 亚洲风情在线资源| www.com.cn成人| 久久三级视频| 日韩网站在线| 成人国产精选| 精品亚洲成人| 欧美亚洲二区| 亚洲另类av| aa亚洲婷婷| 日韩视频网站在线观看| 麻豆精品91| 久久精品电影| 久久99免费视频| 亚洲免费毛片| 欧美黄色精品| 欧美在线看片| 免费观看在线色综合| 免播放器亚洲一区| 日韩免费小视频| 亚洲深夜视频| 精品99在线| 玖玖玖国产精品| 国产精品18| 久久午夜精品一区二区| 热久久久久久久| 欧美成人aaa| 国产精品入口久久| 99视频+国产日韩欧美| 精品国产亚洲日本| 日韩欧美三区| 久久久久99| 婷婷综合一区| 国产欧美日韩在线一区二区| 国产精品一区二区精品视频观看| 亚洲不卡av不卡一区二区| 麻豆国产精品视频| 国产精品午夜av| 国产精品黄色| 激情综合自拍| 亚洲制服欧美另类| 亚洲视频二区| 国产精品多人| 丁香六月综合| 国产偷自视频区视频一区二区| 蜜臀91精品一区二区三区| 国产毛片精品| 一本大道色婷婷在线| 亚洲高清激情| 夜夜嗨av一区二区三区网站四季av| 激情欧美日韩一区| 国产精品流白浆在线观看| 日韩在线不卡| 黄色日韩在线| 国产一区二区三区四区大秀| 久久久久国产| 国产精品一区二区av日韩在线| 国产欧美久久一区二区三区| 久久精品91| 欧美日韩中文一区二区| 91精品精品| 超碰99在线| 国产一区福利| 精品视频91| 成人午夜毛片| 欧美少妇精品| 91精品91| 人人精品人人爱| 国产精品xxx在线观看| 91欧美日韩| 99在线精品免费视频九九视 | 亚洲精品乱码| 麻豆精品视频在线| 日韩精品欧美| 亚洲人成高清| 日韩精品一二三区| 欧美日韩xxxx| 婷婷激情久久| 一区在线观看| 蜜桃av一区| 日韩国产高清在线| 麻豆一区二区在线| 美女av在线免费看| 久久国产亚洲精品| 欧美成人综合| 欧美精品一卡| 视频一区二区三区在线| 日韩有码av| 久久男人av| 国产二区精品| 97精品久久| 97精品国产福利一区二区三区| 久久久91麻豆精品国产一区| 88xx成人免费观看视频库| 亚洲a在线视频| 免费黄网站欧美| 捆绑调教美女网站视频一区| 国产99久久久国产精品成人免费| 伊人成人在线视频| 日韩av午夜在线观看| 黑人精品一区| 日韩精品一级二级| 国产精品精品国产一区二区| 亚洲激情另类| 精品深夜福利视频| 热久久免费视频| 国产一区二区三区亚洲| 成人自拍av| 日本欧美韩国一区三区| 欧美午夜精彩| 国产经典一区| 美女精品网站| 久久精品影视| 九九久久国产| 日韩精选在线| 亚洲午夜在线| se01亚洲视频| 久久精品人人| 国产精品一线天粉嫩av| 国产精品日本欧美一区二区三区| 奇米狠狠一区二区三区| 午夜国产欧美理论在线播放 | 91看片一区| 国产一区二区三区四区五区| 日本综合精品一区| 免费观看久久av| 在线亚洲人成| 久久尤物视频| 国产日韩欧美高清免费| 免费成人在线观看| 99在线|亚洲一区二区| 精精国产xxxx视频在线野外| 久久精品国产亚洲一区二区三区| 日韩精品91亚洲二区在线观看| 亚洲一级黄色| 四虎影视精品| 久久精品欧洲| 精品日本视频| sm捆绑调教国产免费网站在线观看| 国产日韩欧美在线播放不卡| 欧美日韩91| 国产精品一区二区精品| 国产福利一区二区三区在线播放| 日韩精品一区二区三区中文字幕|