隨着互聯網的快速發展,越來越多的應用程序需要用戶進行註冊、登錄和權限管理。使用SpringBootToken可以實現安全的用戶管理,保護敏感資源和數據。在本篇文章中,我們將從多個方面介紹SpringBootToken的使用和相關知識。
一、SpringBootToken登錄
用戶登錄是使用SpringBootToken的第一步,它需要驗證用戶的身份信息是否正確。Spring中提供了一個JWT(JSON Web Token)框架,可以通過JWT實現用戶登錄認證。
JWT作為一種簡潔的、自包含的格式可以在接收方之間傳遞信息。JWT由三部分組成:header、payload和signature。header部分通常由該JWT的類型和所使用的簽名算法組成。payload部分包含了用戶的信息和JWT的過期時間。signature則是根據header、payload以及密鑰生成的哈希值。通過組合這三部分數據,就可以生成JWT。
下面是一個SpringBootToken的登錄代碼示例:
//依賴
io.jsonwebtoken
jjwt
0.7.0
//生成Token
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class JwtTokenUtil {
private static final String CLAIM_KEY_USERNAME = "sub";
private static final String CLAIM_KEY_CREATED = "created";
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
/**
* 通過用戶名生成Token
* @param username 用戶名
* @return Token
*/
public String generateToken(String username) {
Claims claims = Jwts.claims().setSubject(username);
Date now = new Date();
Date expirationDate = new Date(now.getTime() + expiration * 1000);
claims.put(CLAIM_KEY_CREATED, now);
return Jwts.builder()
.setClaims(claims)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 從Token中獲取用戶名
* @param token Token
* @return 用戶名
*/
public String getUsernameFromToken(String token) {
String username;
try {
Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
/**
* 驗證Token是否合法
* @param token Token
* @return 是否合法
*/
public boolean validateToken(String token) {
return !isTokenExpired(token);
}
/**
* 驗證Token是否過期
* @param token Token
* @return 是否過期
*/
private boolean isTokenExpired(String token) {
Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
/**
* 從Token中獲取Token過期時間
* @param token Token
* @return Token過期時間
*/
private Date getExpirationDateFromToken(String token) {
Claims claims = getClaimsFromToken(token);
return claims.getExpiration();
}
/**
* 從Token中獲取Claims
* @param token Token
* @return Claims
*/
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
}
二、SpringBootToken共享
在一些分布式應用中,我們希望將Token存儲在外部的系統中,並通過其他服務來驗證Token。這時候我們需要保證Token的一致性,即任何由一個服務生成的Token都可以被其他服務驗證通過。
為了實現Token的共享,我們可以使用公共的密鑰來對Token進行簽名和驗證。所有需要使用Token的服務都使用相同的公共密鑰來實現簽名和驗證。下面是使用公共密鑰來實現Token共享的代碼示例:
//依賴
io.jsonwebtoken
jjwt
0.7.0
//生成Token
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
@Component
public class JwtTokenUtil {
private static final String CLAIM_KEY_USERNAME = "sub";
private static final String CLAIM_KEY_CREATED = "created";
private static final String CLAIM_KEY_AUDIENCE = "audience";
private static final String AUDIENCE_UNKNOWN = "unknown";
private static final String AUDIENCE_WEB = "web";
private static final String AUDIENCE_MOBILE = "mobile";
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private Long expiration;
/**
* 根據用戶和設備生成Token
* @param username 用戶名
* @param audience 設備
* @return Token
*/
public String generateToken(String username, String audience) {
if (StringUtils.isEmpty(audience)) {
audience = AUDIENCE_UNKNOWN;
}
Claims claims = Jwts.claims().setSubject(username);
claims.put(CLAIM_KEY_CREATED, new Date());
claims.put(CLAIM_KEY_AUDIENCE, audience);
Date now = new Date();
Date expirationDate = new Date(now.getTime() + expiration * 1000);
return Jwts.builder()
.setClaims(claims)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 從Token中獲取用戶名
* @param token Token
* @return 用戶名
*/
public String getUsernameFromToken(String token) {
String username;
try {
Claims claims = getClaimsFromToken(token);
username = claims.getSubject();
} catch (Exception e) {
username = null;
}
return username;
}
/**
* 從Token中獲取Token過期時間
* @param token Token
* @return Token過期時間
*/
public Date getExpirationDateFromToken(String token) {
Claims claims = getClaimsFromToken(token);
return claims.getExpiration();
}
/**
* 驗證Token是否合法
* @param token Token
* @param userDetails 用戶
* @return 是否合法
*/
public boolean validateToken(String token, UserDetails userDetails) {
String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
/**
* 驗證Token是否過期
* @param token Token
* @return 是否過期
*/
private boolean isTokenExpired(String token) {
Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
/**
* 從Token中獲取Claims
* @param token Token
* @return Claims
*/
private Claims getClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
} catch (Exception e) {
claims = null;
}
return claims;
}
}
三、SpringBootToken校驗
在使用SpringBootToken時,安全性非常重要,我們需要對Token進行校驗。校驗的目的是驗證Token的有效性,即Token是否有效、是否被篡改過等。
SpringBootToken提供了一種很方便的方式來進行Token的校驗,即使用攔截器來攔截訪問,然後進行Token校驗。下面是一個SpringBootToken校驗的代碼示例:
/**
* Token攔截器
*/
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.header}")
private String header;
@Value("${jwt.tokenPrefix}")
private String tokenPrefix;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
String token = request.getHeader(header);
if (token != null && token.startsWith(tokenPrefix)) {
token = token.substring(tokenPrefix.length());
String username = jwtTokenUtil.getUsernameFromToken(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(token, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
chain.doFilter(request, response);
}
}
四、SpringBootToken放行
雖然SpringBootToken提供了很好的安全性,但在某些情況下,我們需要放行一些不需要身份認證的資源。與其他的Spring安全機制一樣,SpringBootToken也提供了很好的支持來實現這一目的。
我們可以在WebSecurityConfigurerAdapter中配置用於放行的資源以及需要進行身份驗證的資源。下面是一個配置文件的示例:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private JwtUserDetailsService userDetailsService;
@Autowired
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Value("${jwt.header}")
private String header;
@SuppressWarnings({"rawtypes", "unchecked"})
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();
}
@Bean
public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
return new JwtAuthenticationTokenFilter();
}
@Bean
public JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint() {
return new JwtAuthenticationEntryPoint();
}
/**
* 忽略靜態資源攔截
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/**");
}
}
五、SpringBootToken用什麼比較好選取
在選擇使用什麼框架來實現用戶登錄和授權時,可以根據實際情況來選擇。SpringBootToken提供了很好的支持來實現用戶登錄認證、Token的生成和驗證、Token的共享和資源的放行,使用起來非常方便。
如果您的應用程序需要更多的功能,或者需要更高級的安全性,可以考慮使用其他框架,如Shiro、OAuth2等。這些框架提供了更豐富的授權和權限管理功能,同時也需要更多的配置和實現。
總之,在選擇框架時,需要根據實際情況來選擇,同時也需要考慮到自己的技術水平和開發成本。
六、總結
在本文中,我們詳細介紹了SpringBootToken的使用和相關知識。SpringBootToken不僅可以實現安全的用戶管理,還可以保護敏感資源和數據,保證應用程序的安全性。在使用SpringBootToken時,我們需要考慮安全性、代碼複雜性、開發成本等方面的因素來選擇合適的框架。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/248750.html
微信掃一掃
支付寶掃一掃