From 8d59cc17beded7ab486b039d1f8d4d7624d513c1 Mon Sep 17 00:00:00 2001 From: TS-QD1 Date: Thu, 7 Sep 2023 14:31:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AE=BF=E5=AE=A2=E6=8E=A7?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aspect/GuestControllerAspect.java | 128 ++++++++++++++++++ .../login/guest/GuestProperties.java | 30 ++++ ...GuestUserAuthenticationFailureHandler.java | 24 ++++ .../guest/GuestUserAuthenticationFilter.java | 37 +++++ .../GuestUserAuthenticationProvider.java | 112 +++++++++++++++ .../guest/GuestUserAuthenticationToken.java | 43 ++++++ .../login/guest/GuestUserSecurityConfig.java | 51 +++++++ src/main/resources/application-dev.yml | 5 + .../templates/map/count/map-count.html | 6 +- 9 files changed, 433 insertions(+), 3 deletions(-) create mode 100644 src/main/java/cn/com/tenlion/usercenter/aspect/GuestControllerAspect.java create mode 100644 src/main/java/cn/com/tenlion/usercenter/login/guest/GuestProperties.java create mode 100644 src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFailureHandler.java create mode 100644 src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFilter.java create mode 100644 src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationProvider.java create mode 100644 src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationToken.java create mode 100644 src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserSecurityConfig.java diff --git a/src/main/java/cn/com/tenlion/usercenter/aspect/GuestControllerAspect.java b/src/main/java/cn/com/tenlion/usercenter/aspect/GuestControllerAspect.java new file mode 100644 index 0000000..47f6a35 --- /dev/null +++ b/src/main/java/cn/com/tenlion/usercenter/aspect/GuestControllerAspect.java @@ -0,0 +1,128 @@ +package cn.com.tenlion.usercenter.aspect; + +import cn.com.tenlion.usercenter.login.guest.GuestProperties; +import ink.wgink.common.component.SecurityComponent; +import ink.wgink.exceptions.base.SystemException; +import ink.wgink.pojo.dtos.role.RoleSimpleDTO; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.security.core.parameters.P; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.List; + +@Order(-1) +@Component +@Aspect +public class GuestControllerAspect { + + /** + * 默认新增事务 + */ + private static String[] DEFAULT_SAVE_ARRAY = {"add*", "save*", "insert*", "create*", "new*"}; + /** + * 默认删除事务 + */ + private static String[] DEFAULT_REMOVE_ARRAY = {"delete*", "remove*"}; + /** + * 默认执行事务 + */ + private static String[] DEFAULT_UPDATE_ARRAY = {"update*", "edit*", "reset*"}; + /** + * 默认其它事务 + */ + private static String[] DEFAULT_OTHER_ARRAY = {"send*", "exec*", "set*", "login*", "register*", "sign*", "rest*", "upload*"}; + + @Autowired + private GuestProperties guestProperties; + @Autowired + private SecurityComponent securityComponent; + + @Pointcut("execution(public * *..controller..*.*(..))") + public void apiLogCutPoint() { + } + + /** + * 访客没有曾、删、改权限,只有查看权限 + * + * @param proceedingJoinPoint + * @return + * @throws Throwable + */ + @Around("apiLogCutPoint()") + public Object apiLogAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { + if (guestProperties == null) { + return proceedingJoinPoint.proceed(); + } + // 非访客,不处理 + if (!isGuest()) { + return result(proceedingJoinPoint); + } + Method method = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod(); + // GET不处理 + if (isGetMethod(method)) { + return result(proceedingJoinPoint); + } + throw new SystemException("权限不足"); + } + + private Object result(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { + Object result; + try { + result = proceedingJoinPoint.proceed(); + } catch (Throwable e) { + throw e; + } + return result; + } + + private boolean isGuest() { + if (securityComponent == null) { + return false; + } + if (securityComponent.getCurrentUser() == null) { + return false; + } + if (securityComponent.getCurrentUser().getUserUsername().equalsIgnoreCase("admin")) { + return false; + } + List roles = securityComponent.getCurrentUser().getRoles(); + for (RoleSimpleDTO roleSimpleDTO : roles) { + for (String guestRoleId : guestProperties.getGuestRoleIds()) { + if (StringUtils.equals(roleSimpleDTO.getRoleId(), guestRoleId)) { + return true; + } + } + } + return false; + } + + private boolean isGetMethod(Method method) { + GetMapping getMapping = method.getAnnotation(GetMapping.class); + if (getMapping != null) { + return true; + } + RequestMapping requestMapping = method.getAnnotation(RequestMapping.class); + if (requestMapping == null) { + return false; + } + RequestMethod[] requestMethods = requestMapping.method(); + for (RequestMethod requestMethod : requestMethods) { + if (StringUtils.equalsIgnoreCase(requestMethod.name(), "GET")) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestProperties.java b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestProperties.java new file mode 100644 index 0000000..e139a70 --- /dev/null +++ b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestProperties.java @@ -0,0 +1,30 @@ +package cn.com.tenlion.usercenter.login.guest; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +@ConfigurationProperties(prefix = "guest") +public class GuestProperties { + + private String loginProcess; + private List guestRoleIds; + + public String getLoginProcess() { + return loginProcess; + } + + public void setLoginProcess(String loginProcess) { + this.loginProcess = loginProcess; + } + + public List getGuestRoleIds() { + return guestRoleIds; + } + + public void setGuestRoleIds(List guestRoleIds) { + this.guestRoleIds = guestRoleIds; + } +} diff --git a/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFailureHandler.java b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFailureHandler.java new file mode 100644 index 0000000..e9df238 --- /dev/null +++ b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFailureHandler.java @@ -0,0 +1,24 @@ +package cn.com.tenlion.usercenter.login.guest; + +import org.apache.http.HttpStatus; +import org.apache.http.entity.ContentType; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; + +public class GuestUserAuthenticationFailureHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { + httpServletResponse.setStatus(HttpStatus.SC_OK); + httpServletResponse.setContentType("text/html;charset=utf-8"); + PrintWriter writer = httpServletResponse.getWriter(); + writer.write("
错误
" + e.getMessage() + "
"); + writer.flush(); + } +} diff --git a/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFilter.java b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFilter.java new file mode 100644 index 0000000..f4bb7db --- /dev/null +++ b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationFilter.java @@ -0,0 +1,37 @@ +package cn.com.tenlion.usercenter.login.guest; + +import ink.wgink.login.base.exceptions.UserAuthenticationException; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.AndRequestMatcher; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class GuestUserAuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + protected GuestUserAuthenticationFilter(String loginProcess) { + super(new AntPathRequestMatcher(loginProcess, "GET")); + } + + + + @Override + public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException { + String guest = httpServletRequest.getParameter("guest"); + if (StringUtils.isBlank(guest)) { + throw new UserAuthenticationException("guest不能为空"); + } + GuestUserAuthenticationToken guestUserAuthenticationToken = new GuestUserAuthenticationToken(guest, guest); + guestUserAuthenticationToken.setDetails(authenticationDetailsSource.buildDetails(httpServletRequest)); + return this.getAuthenticationManager().authenticate(guestUserAuthenticationToken); + } + + +} diff --git a/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationProvider.java b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationProvider.java new file mode 100644 index 0000000..a8791dc --- /dev/null +++ b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationProvider.java @@ -0,0 +1,112 @@ +package cn.com.tenlion.usercenter.login.guest; + +import ink.wgink.common.manager.env.EnvManager; +import ink.wgink.exceptions.base.SystemException; +import ink.wgink.interfaces.expand.login.ILoginHandlerService; +import ink.wgink.login.base.authentication.user.UserAuthenticationToken; +import ink.wgink.login.base.consts.IUserCenterConst; +import ink.wgink.login.base.enums.LoginTypeEnum; +import ink.wgink.login.base.exceptions.UserAuthenticationException; +import ink.wgink.login.base.service.user.UserDetailServiceImpl; +import ink.wgink.login.base.service.user.UserLoginService; +import ink.wgink.pojo.bos.LoginUser; +import ink.wgink.service.role.service.IRoleUserService; +import ink.wgink.service.user.enums.UserStateEnum; +import ink.wgink.service.user.enums.UserTypeEnum; +import ink.wgink.service.user.pojo.pos.UserPO; +import ink.wgink.service.user.service.IUserService; +import org.apache.commons.lang3.StringUtils; +import org.apache.kafka.common.protocol.types.Field; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; + +import javax.servlet.http.HttpSession; +import java.util.Arrays; +import java.util.List; + +public class GuestUserAuthenticationProvider implements AuthenticationProvider { + private static final Logger LOG = LoggerFactory.getLogger(GuestUserAuthenticationProvider.class); + + private UserDetailServiceImpl userDetailService; + private IRoleUserService roleUserService; + private ILoginHandlerService loginHandler; + private UserLoginService userLoginService; + private HttpSession httpSession; + private GuestProperties guestProperties; + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + GuestUserAuthenticationToken guestUserAuthenticationToken = (GuestUserAuthenticationToken) authentication; + String username = guestUserAuthenticationToken.getPrincipal().toString(); + httpSession.setAttribute(IUserCenterConst.LOGIN_USERNAME, username); + LoginUser loginUser = (LoginUser) userDetailService.loadUserByUsername(username); + userLoginService.setLoginUserInfo(loginUser); + List roleIds = roleUserService.listRoleIdByUserId(loginUser.getUserId()); + if (!isGuestUser(roleIds)) { + throw new UserAuthenticationException("非访客用户"); + } + // 登录逻辑处理 + loginHandler(loginUser); + // 更新登录信息 + userLoginService.updateUserLoginInfo(loginUser.getUserId(), loginUser.getUserName(), LoginTypeEnum.USERNAME_AND_PASSWORD.getValue()); + UserAuthenticationToken userAuthenticationTokenResult = new UserAuthenticationToken(loginUser, null, loginUser.getAuthorities()); + userAuthenticationTokenResult.setDetails(guestUserAuthenticationToken.getDetails()); + return userAuthenticationTokenResult; + } + + @Override + public boolean supports(Class aClass) { + return GuestUserAuthenticationToken.class.isAssignableFrom(aClass); + } + + private void loginHandler(LoginUser loginUser) { + if (loginHandler != null) { + try { + loginHandler.handle(loginUser); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + throw new UserAuthenticationException("登录异常"); + } + } + } + + private Boolean isGuestUser(List roleIds) { + for (String roleId : roleIds) { + for (String guestRoleId : guestProperties.getGuestRoleIds()) { + if (StringUtils.equals(roleId, guestRoleId)) { + return true; + } + } + } + return false; + } + + public void setUserDetailService(UserDetailServiceImpl userDetailService) { + this.userDetailService = userDetailService; + } + + public void setRoleUserService(IRoleUserService roleUserService) { + this.roleUserService = roleUserService; + } + + + public void setLoginHandler(ILoginHandlerService loginHandler) { + this.loginHandler = loginHandler; + } + + public void setUserLoginService(UserLoginService userLoginService) { + this.userLoginService = userLoginService; + } + + public void setHttpSession(HttpSession httpSession) { + this.httpSession = httpSession; + } + + public void setGuestProperties(GuestProperties guestProperties) { + this.guestProperties = guestProperties; + } +} diff --git a/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationToken.java b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationToken.java new file mode 100644 index 0000000..ed0d2b5 --- /dev/null +++ b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserAuthenticationToken.java @@ -0,0 +1,43 @@ +package cn.com.tenlion.usercenter.login.guest; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +public class GuestUserAuthenticationToken extends AbstractAuthenticationToken { + + private final Object principal; + private Object credentials; + + public GuestUserAuthenticationToken(Object principal, Object credentials) { + super(null); + this.principal = principal; + this.credentials = credentials; + super.setAuthenticated(true); + } + + public GuestUserAuthenticationToken(Object principal, Object credentials, + Collection authorities) { + super(authorities); + this.principal = principal; + this.credentials = credentials; + super.setAuthenticated(true); + } + + @Override + public Object getCredentials() { + return credentials; + } + + @Override + public Object getPrincipal() { + return principal; + } + + @Override + public void eraseCredentials() { + super.eraseCredentials(); + credentials = null; + } +} diff --git a/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserSecurityConfig.java b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserSecurityConfig.java new file mode 100644 index 0000000..07eb3de --- /dev/null +++ b/src/main/java/cn/com/tenlion/usercenter/login/guest/GuestUserSecurityConfig.java @@ -0,0 +1,51 @@ +package cn.com.tenlion.usercenter.login.guest; + +import ink.wgink.interfaces.config.ICustomUserSecurityConfig; +import ink.wgink.interfaces.expand.login.ILoginHandlerService; +import ink.wgink.login.base.service.user.UserDetailServiceImpl; +import ink.wgink.login.base.service.user.UserLoginService; +import ink.wgink.service.role.service.IRoleUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.SecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.DefaultSecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpSession; + +@Component +public class GuestUserSecurityConfig extends SecurityConfigurerAdapter implements ICustomUserSecurityConfig { + + @Autowired + private UserDetailServiceImpl userDetailService; + @Autowired + private UserLoginService userLoginService; + @Autowired + private IRoleUserService roleUserService; + @Autowired + private ILoginHandlerService loginHandlerService; + @Autowired + private HttpSession httpSession; + @Autowired + private GuestProperties guestProperties; + + @Override + public void configure(HttpSecurity builder) throws Exception { + super.configure(builder); + + GuestUserAuthenticationFilter guestUserAuthenticationFilter = new GuestUserAuthenticationFilter(guestProperties.getLoginProcess()); + guestUserAuthenticationFilter.setAuthenticationManager(builder.getSharedObject(AuthenticationManager.class)); + guestUserAuthenticationFilter.setAuthenticationFailureHandler(new GuestUserAuthenticationFailureHandler()); + + GuestUserAuthenticationProvider guestUserAuthenticationProvider = new GuestUserAuthenticationProvider(); + guestUserAuthenticationProvider.setUserDetailService(userDetailService); + guestUserAuthenticationProvider.setUserLoginService(userLoginService); + guestUserAuthenticationProvider.setRoleUserService(roleUserService); + guestUserAuthenticationProvider.setLoginHandler(loginHandlerService); + guestUserAuthenticationProvider.setHttpSession(httpSession); + guestUserAuthenticationProvider.setGuestProperties(guestProperties); + builder.authenticationProvider(guestUserAuthenticationProvider).addFilterBefore(guestUserAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); + } +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 1c8ea7c..21efec7 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -10,6 +10,11 @@ server: encoding: force-response: true +guest: + login-process: /oauth/guest-login + guest-role-ids: + - b71d2127-ed91-4f7f-9f6c-7860f6e0028c + spring: login-url: /oauth/login login-failure: /oauth/login?error diff --git a/src/main/resources/templates/map/count/map-count.html b/src/main/resources/templates/map/count/map-count.html index 5a52c78..cc31fb5 100644 --- a/src/main/resources/templates/map/count/map-count.html +++ b/src/main/resources/templates/map/count/map-count.html @@ -238,7 +238,7 @@ 其中 - 重点信访人 + 涉稳重点 ${data.petitionNum}人 @@ -254,11 +254,11 @@ ${data.crimeReleaseNum}人 - 邪教人员 + 信教群众 ${data.cultistNum}人 - 吸毒人员 + 管控吸毒 ${data.drugAddictNum}人