From df7f6950d13db73a6c3cf099c2eb912d8d0b215a Mon Sep 17 00:00:00 2001 From: valarchie <343928303@qq.com> Date: Tue, 1 Aug 2023 14:02:27 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=96=B0=E5=A2=9EAPI=E7=9A=84?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/controller/app/AppController.java | 39 ++++++ .../controller/common/LoginController.java | 38 ++++++ .../config/JwtAuthenticationFilter.java | 52 +++++++ .../api/customize/config/SecurityConfig.java | 88 ++++++++++++ .../customize/service/JwtTokenService.java | 129 ++++++++++++++++++ .../api/customize/util/ApiEncryptor.java | 12 ++ .../user/base/BaseLoginUser.java | 12 +- 7 files changed, 367 insertions(+), 3 deletions(-) create mode 100644 agileboot-api/src/main/java/com/agileboot/api/controller/app/AppController.java create mode 100644 agileboot-api/src/main/java/com/agileboot/api/controller/common/LoginController.java create mode 100644 agileboot-api/src/main/java/com/agileboot/api/customize/config/JwtAuthenticationFilter.java create mode 100644 agileboot-api/src/main/java/com/agileboot/api/customize/config/SecurityConfig.java create mode 100644 agileboot-api/src/main/java/com/agileboot/api/customize/service/JwtTokenService.java create mode 100644 agileboot-api/src/main/java/com/agileboot/api/customize/util/ApiEncryptor.java diff --git a/agileboot-api/src/main/java/com/agileboot/api/controller/app/AppController.java b/agileboot-api/src/main/java/com/agileboot/api/controller/app/AppController.java new file mode 100644 index 0000000..85fc2e4 --- /dev/null +++ b/agileboot-api/src/main/java/com/agileboot/api/controller/app/AppController.java @@ -0,0 +1,39 @@ +package com.agileboot.api.controller.app; + +import com.agileboot.api.customize.service.JwtTokenService; +import com.agileboot.common.core.base.BaseController; +import com.agileboot.common.core.dto.ResponseDTO; +import lombok.AllArgsConstructor; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 调度日志操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/app") +@AllArgsConstructor +public class AppController extends BaseController { + + private final JwtTokenService jwtTokenService; + + /** + * 访问首页,提示语 + */ + @PreAuthorize("hasAuthority('annie')") + @GetMapping("/list") + public ResponseDTO appLogin() { + return ResponseDTO.ok(); + } + + + + + + + +} diff --git a/agileboot-api/src/main/java/com/agileboot/api/controller/common/LoginController.java b/agileboot-api/src/main/java/com/agileboot/api/controller/common/LoginController.java new file mode 100644 index 0000000..6c0ec6d --- /dev/null +++ b/agileboot-api/src/main/java/com/agileboot/api/controller/common/LoginController.java @@ -0,0 +1,38 @@ +package com.agileboot.api.controller.common; + +import cn.hutool.core.map.MapUtil; +import com.agileboot.api.customize.service.JwtTokenService; +import com.agileboot.common.core.base.BaseController; +import com.agileboot.common.core.dto.ResponseDTO; +import java.util.Map; +import lombok.AllArgsConstructor; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 调度日志操作处理 + * + * @author ruoyi + */ +@RestController +@RequestMapping("/common") +@AllArgsConstructor +public class LoginController extends BaseController { + + private final JwtTokenService jwtTokenService; + + /** + * 访问首页,提示语 + */ + @PostMapping("/app/{appId}/login") + public ResponseDTO appLogin() { + String token = jwtTokenService.generateToken(MapUtil.of("token", "user1")); + return ResponseDTO.ok(token); + } + + + + +} diff --git a/agileboot-api/src/main/java/com/agileboot/api/customize/config/JwtAuthenticationFilter.java b/agileboot-api/src/main/java/com/agileboot/api/customize/config/JwtAuthenticationFilter.java new file mode 100644 index 0000000..9b54f13 --- /dev/null +++ b/agileboot-api/src/main/java/com/agileboot/api/customize/config/JwtAuthenticationFilter.java @@ -0,0 +1,52 @@ +package com.agileboot.api.customize.config; + +import com.agileboot.api.customize.service.JwtTokenService; +import com.agileboot.infrastructure.user.app.AppLoginUser; +import io.jsonwebtoken.Claims; +import java.io.IOException; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +/** + * token过滤器 验证token有效性 + * 继承OncePerRequestFilter类的话 可以确保只执行filter一次, 避免执行多次 + * @author valarchie + */ +@Component +@Slf4j +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + @Autowired + private JwtTokenService jwtTokenService; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + String tokenFromRequest = jwtTokenService.getTokenFromRequest(request); + + if (tokenFromRequest != null) { + Claims claims = jwtTokenService.parseToken(tokenFromRequest); + String token = (String) claims.get("token"); + // 根据token去查缓存里面 有没有对应的App用户 + // 没有的话 再去数据库中查询 + if (token != null && token.equals("user1")) { + AppLoginUser loginUser = new AppLoginUser(23232323L, false, "dasdsadsds"); + loginUser.grantAppPermission("annie"); + UsernamePasswordAuthenticationToken suer1 = new UsernamePasswordAuthenticationToken(loginUser, null, + loginUser.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(suer1); + } + } + + filterChain.doFilter(request, response); + } +} diff --git a/agileboot-api/src/main/java/com/agileboot/api/customize/config/SecurityConfig.java b/agileboot-api/src/main/java/com/agileboot/api/customize/config/SecurityConfig.java new file mode 100644 index 0000000..0abba92 --- /dev/null +++ b/agileboot-api/src/main/java/com/agileboot/api/customize/config/SecurityConfig.java @@ -0,0 +1,88 @@ +package com.agileboot.api.customize.config; + +import com.agileboot.common.core.dto.ResponseDTO; +import com.agileboot.common.exception.ApiException; +import com.agileboot.common.exception.error.ErrorCode.Client; +import com.agileboot.common.utils.ServletHolderUtil; +import com.agileboot.common.utils.jackson.JacksonUtil; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +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.EnableWebSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.filter.CorsFilter; + +/** + * 主要配置登录流程逻辑涉及以下几个类 + + * @author valarchie + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled = true) +@RequiredArgsConstructor +public class SecurityConfig { + /** + * token认证过滤器 + */ + @NonNull + private JwtAuthenticationFilter jwtTokenFilter; + + + /** + * 跨域过滤器 + */ + @NonNull + private CorsFilter corsFilter; + + + /** + * 登录异常处理类 + * 用户未登陆的话 在这个Bean中处理 + */ + @Bean + public AuthenticationEntryPoint customAuthenticationEntryPoint() { + return (request, response, exception) -> { + ResponseDTO responseDTO = ResponseDTO.fail( + new ApiException(Client.COMMON_NO_AUTHORIZATION, request.getRequestURI()) + ); + ServletHolderUtil.renderString(response, JacksonUtil.to(responseDTO)); + }; + } + + + + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + httpSecurity.csrf().disable() + // 不配这个错误处理的话 会直接返回403 + .exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint()) + .and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 禁用 session + .and() + .authorizeRequests() + .antMatchers("/common/**").permitAll() + .anyRequest().authenticated() + .and() + // 禁用 X-Frame-Options 响应头。下面是具体解释: + // X-Frame-Options 是一个 HTTP 响应头,用于防止网页被嵌入到其他网页的 、