JWT是一种用于身份验证和授权的开放标准,它可以在客户端和服务器之间安全地传输信息
前言:
在使用JWT进行身份验证时,用户在登录成功后会收到一个包含JWT的令牌,该令牌会存储在客户端(例如浏览器的Cookie或本地存储)中。 客户端在每次请求时都会携带该JWT令牌,服务器通过验证该令牌来确认用户的身份和权限 如何实现登录认证 登录成功通过JWT生成一串字符串作为Token,返回给前端 前端每次请求的时候都在请求头中携带上这个Token 后端每次都使用JWT对该Token进行校验,以此来判断用户是否登录 实现步骤
配置Spring Security:
创建一个配置类,继承自WebSecurityConfigurerAdapter,并添加@Configuration和@EnableWebSecurity注解。 在配置类中,重写configure(HttpSecurity http)方法 @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { /** * 自定义用户认证逻辑 */ @Autowired private UserDetailsService userDetailsService;
/**
* 认证失败处理类
*/
@Autowired
private AuthenticationEntryPointImpl unauthorizedHandler;
// 配置登录认证的URL、身份验证逻辑和访问权限
// ...
} @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity // CSRF禁用,因为不使用session .csrf().disable() // 认证失败处理类 .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() // 基于token,所以不需要session .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 用户登录:
创建一个认证控制器,用于处理用户登录请求。 在认证控制器中,注入AuthenticationManager和JwtTokenUtil,用于进行身份验证和生成JWT令牌 @RestController public class AuthController { @Autowired private AuthenticationManager authenticationManager; @Autowired private JwtTokenUtil jwtTokenUtil; @Autowired private UserService userService;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
// 验证用户身份信息
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
// 生成JWT令牌
UserDetails userDetails = userService.loadUserByUsername(loginRequest.getUsername());
String token = jwtTokenUtil.generateToken(userDetails);
// 返回JWT令牌给客户端
return ResponseEntity.ok(new JwtResponse(token));
}
} JWT令牌生成和验证:
创建一个JWT工具类,用于生成和验证JWT令牌。 在JWT工具类中,设置JWT令牌的有效期等 public class JwtTokenUtils { private static final String EMPLOYEE_ID_KEY = ""; private static final String STUDENT_ID_KEY = ""; private static final String TOKEN_TYPE_KEY = "*";; private static final String SECRE_DEVICE_KEY = "secretdeviceheliplay!";
/**
* 生成Token
* @param employeeId 用户标识(唯一)
* @return
*/
public static String createToken(Long employeeId, String tokenType, String scope) {
Algorithm algorithm = Algorithm.HMAC256(SECRE_KEY);
Date expireTime = new Date(System.currentTimeMillis() + TOKEN_EXPIRE_TIME);
String token = JWT.create()
.withIssuer(ISSUSER)
.withIssuedAt(new Date())
.withExpiresAt(expireTime)
.withClaim(EMPLOYEE_ID_KEY, employeeId)
.withClaim(TOKEN_TYPE_KEY, tokenType)
.withClaim(SCOPE_KEY, scope)
.sign(algorithm);
return token;
}
/**
* 生成Token
* @param employeeId 用户标识(唯一)
* @return
*/
public static String createDeviceToken(Long studentId, String tokenType, String scope) {
Algorithm algorithm = Algorithm.HMAC256(SECRE_DEVICE_KEY);
Date expireTime = new Date(System.currentTimeMillis() + TOKEN_EXPIRE_TIME);
String token = JWT.create()
.withIssuer(ISSUSER)
.withIssuedAt(new Date())
.withExpiresAt(expireTime)
.withClaim(STUDENT_ID_KEY, studentId)
.withClaim(TOKEN_TYPE_KEY, tokenType)
.withClaim(SCOPE_KEY, scope)
.sign(algorithm);
return token;
}
} 授权访问控制:
在Spring Security的配置类中,根据JWT令牌中的用户身份和权限信息,进行访问控制的配置。 可以使用hasRole、hasAnyRole、hasAuthority @Service("ss") public class PermissionService { /** 所有权限标识 / private static final String ALL_PERMISSION = "::";
/** 管理员角色权限标识 */
private static final String SUPER_ADMIN = "admin";
private static final String ROLE_DELIMETER = ",";
private static final String PERMISSION_DELIMETER = ",";
/**
* 验证用户是否具备某权限
*
* @param permission 权限字符串
* @return 用户是否具备某权限
*/
public boolean hasPermi(String permission)
{
if (StringUtils.isEmpty(permission))
{
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
return hasPermissions(loginUser.getPermissions(), permission);
}
/**
* 验证用户是否不具备某权限,与 hasPermi逻辑相反
*
* @param permission 权限字符串
* @return 用户是否不具备某权限
*/
public boolean lacksPermi(String permission)
{
return hasPermi(permission) != true;
}
/**
* 验证用户是否具有以下任意一个权限
*
* @param permissions 以 PERMISSION_NAMES_DELIMETER 为分隔符的权限列表
* @return 用户是否具有以下任意一个权限
*/
public boolean hasAnyPermi(String permissions)
{
if (StringUtils.isEmpty(permissions))
{
return false;
}
LoginUser loginUser = SecurityUtils.getLoginUser();
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
Set<String> authorities = loginUser.getPermissions();
for (String permission : permissions.split(PERMISSION_DELIMETER))
{
if (permission != null && hasPermissions(authorities, permission))
{
return true;
}
}
return false;
}
... }
结论 通过以上配置,我们可以利用Spring Security和JWT实现登录认证。每次登录都会生成不同的token值,每次访问接口都需要携带token验证,保证了数据的安全性 结尾语 以上代码只是部分示例,请根据实际情况调整