Spring Security的AuthenticationEntryPoint类,它拒绝每个未经身份验证的请求并发送错误代码401
package cn.soboys.kmall.security.config; import cn.soboys.kmall.common.ret.Result; import cn.soboys.kmall.common.ret.ResultCode; import cn.soboys.kmall.common.ret.ResultResponse; import cn.soboys.kmall.common.utils.ResponseUtil; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.Serializable; /** * @author kenx * @version 1.0 * @date 2021/8/5 22:30 * @webSite https://www.soboys.cn/ * 此类继承Spring Security的AuthenticationEntryPoint类, * 并重写其commence。它拒绝每个未经身份验证的请求并发送错误代码401。 */ @Component public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable { /** * 此类继承Spring Security的AuthenticationEntryPoint类,并重写其commence。 * 它拒绝每个未经身份验证的请求并发送错误代码401 * * @param httpServletRequest * @param httpServletResponse * @param e * @throws IOException * @throws ServletException */ @Override public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { Result result = ResultResponse.failure(ResultCode.UNAUTHORIZED, "请先登录"); ResponseUtil.responseJson(httpServletResponse, result); } }JwtRequestFilter 任何请求都会执行此类检查请求是否具有有效的JWT令牌。如果它具有有效的JWT令牌,则它将在上下文中设置Authentication,以指定当前用户已通过身份验证。
package cn.soboys.kmall.security.config; import cn.soboys.kmall.common.utils.ConstantFiledUtil; import cn.soboys.kmall.security.service.IUserService; import cn.soboys.kmall.security.utils.JwtTokenUtil; import io.jsonwebtoken.ExpiredJwtException; import lombok.extern.slf4j.Slf4j; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * @author kenx * @version 1.0 * @date 2021/8/5 22:27 * @webSite https://www.soboys.cn/ * 任何请求都会执行此类 * 检查请求是否具有有效的JWT令牌。如果它具有有效的JWT令牌, * 则它将在上下文中设置Authentication,以指定当前用户已通过身份验证。 */ @Component @Slf4j public class JwtRequestFilter extends OncePerRequestFilter { //用户数据源 private IUserService userService; //生成jwt 的token private JwtTokenUtil jwtTokenUtil; public JwtRequestFilter(IUserService userService,JwtTokenUtil jwtTokenUtil) { this.userService = userService; this.jwtTokenUtil = jwtTokenUtil; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { final String requestTokenHeader = request.getHeader(ConstantFiledUtil.AUTHORIZATION_TOKEN); String username = null; String jwtToken = null; // JWT Token is in the form "Bearer token". Remove Bearer word and get only the Token if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) { jwtToken = requestTokenHeader.substring(7); try { username = jwtTokenUtil.getUsernameFromToken(jwtToken); } catch (IllegalArgumentException e) { log.error("Unable to get JWT Token"); } catch (ExpiredJwtException e) { log.error("JWT Token has expired"); } } else { //logger.warn("JWT Token does not begin with Bearer String"); } //Once we get the token validate it. if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userService.loadUserByUsername(username); // if token is valid configure Spring Security to manually set authentication if (jwtTokenUtil.validateToken(jwtToken, userDetails)) { //保存用户信息和权限信息 UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); usernamePasswordAuthenticationToken .setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); // After setting the Authentication in the context, we specify // that the current user is authenticated. So it passes the Spring Security Configurations successfully. SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); } } filterChain.doFilter(request, response); } } 配置Spring Security 配置类SecurityConfig
自定义Spring Security的时候我们需要继承自WebSecurityConfigurerAdapter来完成,相关配置重写对应 方法
此处使用了 BCryptPasswordEncoder 密码加密