diff --git a/IDEA/src/main/java/com/example/api/security/JwtAuthorizationFilter.java b/IDEA/src/main/java/com/example/api/security/JwtAuthorizationFilter.java new file mode 100644 index 00000000..56554fd2 --- /dev/null +++ b/IDEA/src/main/java/com/example/api/security/JwtAuthorizationFilter.java @@ -0,0 +1,63 @@ +package com.example.api.security; + +import com.example.api.model.support.ResponseResult; // 导入自定义响应结果类 +import com.example.api.utils.JwtTokenUtil; // 导入JWT工具类 +import com.example.api.utils.ResponseUtil; // 导入响应工具类 +import org.springframework.security.authentication.AuthenticationManager; // 导入认证管理器 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; // 导入用户名密码认证令牌 +import org.springframework.security.core.authority.SimpleGrantedAuthority; // 导入简单授权对象 +import org.springframework.security.core.context.SecurityContextHolder; // 导入安全上下文持有者 +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; // 导入基本认证过滤器 + +import javax.servlet.FilterChain; // 导入过滤器链 +import javax.servlet.ServletException; // 导入Servlet异常 +import javax.servlet.http.HttpServletRequest; // 导入HTTP请求 +import javax.servlet.http.HttpServletResponse; // 导入HTTP响应 +import java.io.IOException; // 导入IO异常 +import java.util.ArrayList; // 导入ArrayList +import java.util.List; // 导入List + +/** + * JWT认证过滤器,从Request的Authorization Header获取JWT, + * 解析JWT授权发放token。 + */ +public class JwtAuthorizationFilter extends BasicAuthenticationFilter { + + public JwtAuthorizationFilter(AuthenticationManager authenticationManager) { + super(authenticationManager); + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) + throws IOException, ServletException { + + // 从Request Header取出Token + String token = request.getHeader(JwtTokenUtil.TOKEN_HEADER); + + // Token为空放行 + // 如果接下来进入的URL不是公共的地址SpringSecurity会返回403的错误 + if (token == null || !JwtTokenUtil.checkToken(token)) { + chain.doFilter(request, response); + return; + } + + // 判断JWT Token是否过期 + if (JwtTokenUtil.isExpiration(token)) { + ResponseUtil.writeJson(response, new ResponseResult<>(403, "令牌已过期, 请重新登录")); + return; + } + + // 解析token + String username = JwtTokenUtil.getUsername(token); + List tokenRoles = JwtTokenUtil.getTokenRoles(token); + ArrayList roles = new ArrayList<>(); + for (String role : tokenRoles) { + roles.add(new SimpleGrantedAuthority(role)); + } + // 向SpringSecurity的Context中加入认证信息 + SecurityContextHolder.getContext().setAuthentication( + new UsernamePasswordAuthenticationToken(username, null, roles)); + + super.doFilterInternal(request, response, chain); + } +} diff --git a/IDEA/src/main/java/com/example/api/security/SecurityConfiguration.java b/IDEA/src/main/java/com/example/api/security/SecurityConfiguration.java new file mode 100644 index 00000000..a55449b2 --- /dev/null +++ b/IDEA/src/main/java/com/example/api/security/SecurityConfiguration.java @@ -0,0 +1,61 @@ +package com.example.api.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * HTTP验证规则 + * + * @param http h + * @throws Exception e + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + + //开启跨域 + http.csrf().disable().cors(); + + //禁用session + http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + + //添加自定义的jwt过滤器 + http.addFilter(new JwtAuthorizationFilter(authenticationManagerBean())); + + } + + /** + * SpringSecurity有默认的跨域配置 会无法放行RequestHeader带有"Authorization"请求 + * 防止前端请求api报出cors error + * + * @return * + */ + @Bean + CorsConfigurationSource corsConfigurationSource() { + final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.addAllowedHeader("*"); + corsConfiguration.addAllowedHeader("DELETE"); + corsConfiguration.addAllowedMethod("*"); + corsConfiguration.addAllowedOrigin("*"); + source.registerCorsConfiguration("/**", corsConfiguration); + return source; + } + +}