随着互联网的快速发展,越来越多的应用程序需要用户进行注册、登录和权限管理。使用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/n/248750.html