From eee34eec81ade6b384847d024768dc8061542d2c Mon Sep 17 00:00:00 2001 From: cheney <1251790704@qq.com> Date: Fri, 6 Jan 2023 18:11:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E5=AF=BC=E5=87=BA=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E4=BC=98=E5=8C=96=EF=BC=8C=E7=99=BB=E5=BD=95=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=8B=A6=E6=88=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 ++ .../iasf/common/config/WebMvcConfigurer.java | 19 ++++ .../exception/code/BaseResponseCode.java | 2 +- .../handler/RestExceptionHandler.java | 13 ++- .../huoran/iasf/common/filter/AuthFilter.java | 97 +++++++++++-------- .../shiro/CustomAccessControlFilter.java | 35 +++++-- .../huoran/iasf/common/shiro/ShiroConfig.java | 88 ++++++++++++++--- .../huoran/iasf/common/utils/Constant.java | 5 + .../iasf/controller/DeptController.java | 4 +- .../iasf/controller/ExceptionController.java | 24 +++++ .../iasf/controller/PermissionController.java | 2 +- .../iasf/controller/RoleController.java | 2 +- .../controller/RolePermissionController.java | 2 +- .../iasf/controller/SiteController.java | 18 ++-- .../iasf/controller/SysLogController.java | 9 +- .../iasf/controller/UserController.java | 10 +- .../iasf/controller/UserDeptController.java | 2 +- .../iasf/service/HttpApiSessionService.java | 6 +- .../iasf/service/HttpSessionService.java | 11 ++- .../iasf/service/impl/UserServiceImpl.java | 15 ++- src/main/resources/whiteList.properties | 2 - 21 files changed, 272 insertions(+), 100 deletions(-) create mode 100644 src/main/java/com/huoran/iasf/controller/ExceptionController.java delete mode 100644 src/main/resources/whiteList.properties diff --git a/pom.xml b/pom.xml index 63f303b..8f3f0a2 100644 --- a/pom.xml +++ b/pom.xml @@ -52,6 +52,12 @@ + + org.springframework.boot + spring-boot-configuration-processor + true + + org.apache.commons diff --git a/src/main/java/com/huoran/iasf/common/config/WebMvcConfigurer.java b/src/main/java/com/huoran/iasf/common/config/WebMvcConfigurer.java index 3eb0fe0..a5e4615 100644 --- a/src/main/java/com/huoran/iasf/common/config/WebMvcConfigurer.java +++ b/src/main/java/com/huoran/iasf/common/config/WebMvcConfigurer.java @@ -15,6 +15,9 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.ResourceHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; @@ -41,6 +44,22 @@ public class WebMvcConfigurer extends WebMvcConfigurationSupport { private FileUploadProperties fileUploadProperties; + private CorsConfiguration buildConfig() { + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.addAllowedHeader("*"); // 允许任何头 + corsConfiguration.addAllowedOrigin("*"); // 允许任何头 + corsConfiguration.addAllowedMethod("*"); // 允许任何方法(post、get等) + return corsConfiguration; + } + + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); // 对接口配置跨域设置 + return new CorsFilter(source); + } + + /** * 使用阿里 FastJson 作为JSON MessageConverter */ diff --git a/src/main/java/com/huoran/iasf/common/exception/code/BaseResponseCode.java b/src/main/java/com/huoran/iasf/common/exception/code/BaseResponseCode.java index bab308c..49a6691 100644 --- a/src/main/java/com/huoran/iasf/common/exception/code/BaseResponseCode.java +++ b/src/main/java/com/huoran/iasf/common/exception/code/BaseResponseCode.java @@ -35,7 +35,7 @@ public enum BaseResponseCode implements ResponseCodeInterface { SUCCESS(200, "success"), EXCEL_FILE_FORMAT_ERROR(40007, "请根据模板使用说明录入正确的用户信息!"), - TOKEN_ERROR(401001, "登录凭证已过期,请重新登录"), + TOKEN_ERROR(401, "登录凭证已过期,请重新登录"), DATA_ERROR(401003, "传入数据异常"), NOT_ACCOUNT(401004, "该用户不存在,请先注册"), USER_LOCK(401005, "该用户已被锁定,请联系运营人员"), diff --git a/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java b/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java index 61b1380..5be1cef 100644 --- a/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java +++ b/src/main/java/com/huoran/iasf/common/exception/handler/RestExceptionHandler.java @@ -5,9 +5,11 @@ import com.huoran.iasf.common.exception.BusinessException; import com.huoran.iasf.common.exception.code.BaseResponseCode; import com.huoran.iasf.common.utils.R; import lombok.extern.slf4j.Slf4j; +import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authz.AuthorizationException; import org.springframework.validation.BindingResult; import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -24,8 +26,8 @@ import java.util.concurrent.atomic.AtomicReference; * @version V1.0 * @date 2022年7月28日 */ -@RestControllerAdvice @Slf4j +@RestControllerAdvice public class RestExceptionHandler { /** @@ -37,11 +39,18 @@ public class RestExceptionHandler { return R.getResult(BaseResponseCode.SYSTEM_BUSY); } + @ExceptionHandler(AuthenticationException.class) + public R authenticationException(AuthenticationException e) { + log.error("Exception,exception:{}", e, e); +// throw new BusinessException(BaseResponseCode.TOKEN_ERROR); + return new R(BaseResponseCode.TOKEN_ERROR.getCode(), BaseResponseCode.TOKEN_ERROR.getMsg()); + } + /** * 自定义全局异常处理 */ @ExceptionHandler(value = BusinessException.class) - R businessExceptionHandler(BusinessException e) { + public R businessExceptionHandler(BusinessException e) { log.error("Exception,exception:{}", e, e); BaseResponseCode em = e.getBaseResponseCode(); return new R(em.getCode(), em.getMsg()); diff --git a/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java b/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java index af972ed..87702ac 100644 --- a/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java +++ b/src/main/java/com/huoran/iasf/common/filter/AuthFilter.java @@ -1,14 +1,18 @@ package com.huoran.iasf.common.filter; -import com.alibaba.fastjson.JSON; -import com.huoran.iasf.common.utils.R; -import com.huoran.iasf.service.HttpApiSessionService; + +import com.huoran.iasf.common.exception.BusinessException; +import com.huoran.iasf.common.exception.code.BaseResponseCode; +import com.huoran.iasf.common.utils.Constant; import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; +import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; -import javax.annotation.Resource; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; @@ -16,33 +20,49 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Arrays; -import static com.huoran.iasf.service.HttpApiSessionService.USER_ID_KEY; -import static com.huoran.iasf.service.HttpApiSessionService.USER_USERNAME_KEY; +import static com.huoran.iasf.service.HttpApiSessionService.*; +import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; +/** + * shiro过滤器 登录用户权限认证授权 + * @author cheney + * @version V1.0 + * @date 2022年7月28日 + */ @Slf4j -@WebFilter(filterName = "authFilter", urlPatterns = "/iasf/*") +@WebFilter(filterName = "tokenFilter", urlPatterns = "/**") @Order(1) +//@Component public class AuthFilter implements Filter { /** * 白名单 */ private static final String[] whiteList = {"/iasf/sys/user/login", - "/iasf/sys/exportFailure"}; + "/iasf/sys/exportFailure","/iasf/sys/getVerify","/iasf/doc.html"}; - @Resource - HttpApiSessionService httpApiSessionService; - //需要拦截的地址 + //需要拦截的地址,验证token是否存在及有效 @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + @SneakyThrows + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { + //每一次的请求先校验cookie +// HttpServletResponse httpResponse = (HttpServletResponse) response; +// HttpServletRequest httpRequest = (HttpServletRequest) request; +// httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("Origin")); +// httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod()); +// httpResponse.setHeader("Access-Control-Max-Age", "3600"); +// httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers")); +// chain.doFilter(request, response); + HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; - resp.setHeader("Access-Control-Allow-Origin","*"); - resp.setHeader("Access-Control-Allow-Credentials", "true"); - resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT"); - resp.setHeader("Access-Control-Allow-Headers", "*"); + resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); + resp.setHeader("Access-Control-Allow-Methods", req.getMethod()); + resp.setHeader("Access-Control-Max-Age", "3600"); + resp.setHeader("Access-Control-Allow-Headers", req.getHeader("Access-Control-Request-Headers")); String url = req.getRequestURI(); log.info("url:{}", url); + if (Arrays.asList(whiteList).contains(url)) { chain.doFilter(request, response); } else { @@ -55,37 +75,38 @@ public class AuthFilter implements Filter { } //token为空返回 if (StringUtils.isBlank(token)) { - resp.setStatus(401); - responseResult(resp, R.fail("token不能为空")); + request.setAttribute("filterError", new BusinessException(BaseResponseCode.TOKEN_ERROR)); + // 指定处理该请求的处理器 + request.getRequestDispatcher(Constant.ERROR_CONTROLLER_PATH).forward(request, response); } // 校验并解析token,如果token过期或者篡改,则会返回null - Claims claims = httpApiSessionService.checkJWT(token); + Claims claims = checkJWT(token); if (null == claims) { - resp.setStatus(401); - responseResult(resp, R.fail("登陆失效,请重新登陆")); + request.setAttribute("filterError", new BusinessException(BaseResponseCode.TOKEN_ERROR)); + // 指定处理该请求的处理器 + request.getRequestDispatcher(Constant.ERROR_CONTROLLER_PATH).forward(request, response); + }else { + // 校验通过后,设置用户信息到request里,在Controller中从Request域中获取用户信息 + request.setAttribute(USER_ID_KEY, claims.get(USER_ID_KEY)); + request.setAttribute(USER_USERNAME_KEY, claims.get(USER_USERNAME_KEY)); } - //TODO 校验用户状态等 - - // 校验通过后,设置用户信息到request里,在Controller中从Request域中获取用户信息 - assert claims != null; - request.setAttribute(USER_ID_KEY, claims.get(USER_ID_KEY)); - request.setAttribute(USER_USERNAME_KEY, claims.get(USER_USERNAME_KEY)); + chain.doFilter(request, response); } } -/** - * responseResult - * @param response - * @param result*/ - private void responseResult(HttpServletResponse response, R result) { - response.setCharacterEncoding("UTF-8"); - response.setHeader("Content-type", "application/json;charset=UTF-8"); - // response.setStatus(200); + /** + * 校验token + */ + public Claims checkJWT(String token) { + try { - response.getWriter().write(JSON.toJSONString(result)); - } catch (IOException ex) { - log.error(ex.getMessage()); + final Claims claims = Jwts.parser().setSigningKey(APP_SECRET). + parseClaimsJws(token).getBody(); + return claims; + } catch (Exception e) { + return null; } } + } diff --git a/src/main/java/com/huoran/iasf/common/shiro/CustomAccessControlFilter.java b/src/main/java/com/huoran/iasf/common/shiro/CustomAccessControlFilter.java index 07d07ca..79744e0 100644 --- a/src/main/java/com/huoran/iasf/common/shiro/CustomAccessControlFilter.java +++ b/src/main/java/com/huoran/iasf/common/shiro/CustomAccessControlFilter.java @@ -11,20 +11,25 @@ import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.AccessControlFilter; +import org.apache.shiro.web.util.WebUtils; +import org.springframework.http.HttpStatus; import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; + /** - * 自定义过滤器 - * + * shiro过滤器 登录用户权限认证授权 * @author cheney * @version V1.0 * @date 2022年7月28日 @@ -32,6 +37,21 @@ import java.nio.charset.StandardCharsets; @Slf4j public class CustomAccessControlFilter extends AccessControlFilter { +// @Override +// protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception { +// HttpServletRequest httpRequest = WebUtils.toHttp(request); +// HttpServletResponse httpResponse = WebUtils.toHttp(response); +// if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) { +// httpResponse.setHeader("Access-control-Allow-Origin", httpRequest.getHeader("Origin")); +// httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod()); +// // httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT"); +// httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers")); +// httpResponse.setStatus(HttpStatus.OK.value()); +// return false; +// } +// return super.preHandle(request, response); +// } + @Override protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) { @@ -41,7 +61,7 @@ public class CustomAccessControlFilter extends AccessControlFilter { @Override protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; - try { +// try { Subject subject = getSubject(servletRequest, servletResponse); System.out.println(subject.isAuthenticated() + ""); System.out.println(HttpContextUtils.isAjaxRequest(request)); @@ -49,16 +69,19 @@ public class CustomAccessControlFilter extends AccessControlFilter { log.info(request.getRequestURL().toString()); //从header中获取token String token = request.getHeader(Constant.ACCESS_TOKEN); + System.out.println("token===============" + token); //如果header中不存在token,则从参数中获取token if (StringUtils.isEmpty(token)) { token = request.getParameter(Constant.ACCESS_TOKEN); } if (StringUtils.isEmpty(token)) { - throw new BusinessException(BaseResponseCode.TOKEN_ERROR); + request.setAttribute("filterError", new BusinessException(BaseResponseCode.TOKEN_ERROR)); + // 指定处理该请求的处理器 + request.getRequestDispatcher(Constant.ERROR_CONTROLLER_PATH).forward(request, servletResponse); } UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(token, token); getSubject(servletRequest, servletResponse).login(usernamePasswordToken); - } catch (BusinessException exception) { + /*} catch (BusinessException exception) { if (HttpContextUtils.isAjaxRequest(request)) { customResponse(exception.getBaseResponseCode().getCode(), exception.getMessage(), servletResponse); } else if (exception.getBaseResponseCode().getCode() == BaseResponseCode.TOKEN_ERROR.getCode()) { @@ -93,7 +116,7 @@ public class CustomAccessControlFilter extends AccessControlFilter { servletRequest.getRequestDispatcher("/index/500").forward(servletRequest, servletResponse); } return false; - } + }*/ return true; } diff --git a/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java b/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java index a7f2e4d..75684c7 100644 --- a/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java +++ b/src/main/java/com/huoran/iasf/common/shiro/ShiroConfig.java @@ -1,7 +1,7 @@ -/* package com.huoran.iasf.common.shiro; import com.huoran.iasf.common.config.FileUploadProperties; +import com.huoran.iasf.common.filter.AuthFilter; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; @@ -9,20 +9,21 @@ import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; import javax.annotation.Resource; import javax.servlet.Filter; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; -*/ /** * ShiroConfig * * @author cheney * @version V1.0 - * @date 2022年7月28日 - *//* + * @date 2022年7月28日*/ + @Configuration @EnableConfigurationProperties(FileUploadProperties.class) @@ -36,9 +37,8 @@ public class ShiroConfig { return new CustomHashedCredentialsMatcher(); } -*/ /** - * 创建realm*//* + * 创建realm*/ @Bean public CustomRealm customRealm() { @@ -56,7 +56,7 @@ public class ShiroConfig { } - @Bean + /*@Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { //整个shiro执行过程: 过滤器、认证、授权 @@ -70,8 +70,7 @@ public class ShiroConfig { shiroFilterFactoryBean.setFilters(filtersMap); Map filterChainDefinitionMap = new LinkedHashMap<>(); // 配置不会被拦截的链接 顺序判断 - */ -/*filterChainDefinitionMap.put("/sys/user/login", "anon"); + *//* filterChainDefinitionMap.put("/sys/user/login", "anon"); filterChainDefinitionMap.put("/sys/user/token", "anon"); filterChainDefinitionMap.put("/sys/getVerify", "anon"); filterChainDefinitionMap.put("/sys/checkVerify", "anon"); @@ -94,22 +93,84 @@ public class ShiroConfig { filterChainDefinitionMap.put("/layui/**", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/layui-ext/**", "anon"); - filterChainDefinitionMap.put("/app/api/**", "anon");*//* + filterChainDefinitionMap.put("/app/api/**", "anon"); filterChainDefinitionMap.put("/sys/getVerify", "anon"); - filterChainDefinitionMap.put("/sys/user/login", "anon"); + filterChainDefinitionMap.put("/sys/user/login", "anon");*//* filterChainDefinitionMap.put("/**", "token,authc"); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; + }*/ + + @Bean + public ShiroFilterFactoryBean shirFilter() { + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + shiroFilterFactoryBean.setLoginUrl("/login"); + shiroFilterFactoryBean.setSecurityManager(securityManager()); + Map filterMap = new HashMap<>(); + + // 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 :这是一个坑呢,一不小心代码就不好使了; + // ① authc:所有url都必须认证通过才可以访问; ② anon:所有url都都可以匿名访问 + + //过滤器1 + filterMap.put("token", new AuthFilter()); + //过滤器2 + //用来校验token + filterMap.put("authc", new CustomAccessControlFilter()); + shiroFilterFactoryBean.setFilters(filterMap); + Map filterChainDefinitionMap = new LinkedHashMap<>(); + // 配置不会被拦截的链接 顺序判断 + filterChainDefinitionMap.put("/sys/user/login", "anon"); + filterChainDefinitionMap.put("/sys/user/token", "anon"); + filterChainDefinitionMap.put("/sys/getVerify", "anon"); + filterChainDefinitionMap.put("/sys/checkVerify", "anon"); + filterChainDefinitionMap.put("/sysFiles/preview/**", "anon"); + filterChainDefinitionMap.put("/sysContent/findById", "anon"); + filterChainDefinitionMap.put("/sysColumn/findById", "anon"); + filterChainDefinitionMap.put("/sysContent/articlePreview", "anon"); + filterChainDefinitionMap.put("/sysContent/newlyPublishedArticles", "anon"); + filterChainDefinitionMap.put("/sysColumn/listWithTreeMenuVisible", "anon"); + filterChainDefinitionMap.put("/sysContent/hotContent", "anon"); + filterChainDefinitionMap.put("/sysColumn/listWithTree", "anon"); + filterChainDefinitionMap.put("/sysColumnLongPage/getLongPageInformation", "anon"); + filterChainDefinitionMap.put("/favicon.ico", "anon"); + filterChainDefinitionMap.put("/sysColumn/queryArticlesByColumnType", "anon"); + filterChainDefinitionMap.put("/content/label/queryAllArticleSubjectTags", "anon"); + filterChainDefinitionMap.put("/sysColumn/oneLevelChecksThemAll", "anon"); + filterChainDefinitionMap.put("/sysColumn/getTheFullArticleByColumn", "anon"); + filterChainDefinitionMap.put("/sys/exportFailure", "anon"); + /*filterChainDefinitionMap.put("/index/**", "anon"); + filterChainDefinitionMap.put("/doc.html", "anon"); + filterChainDefinitionMap.put("/swagger-resources/**", "anon"); + filterChainDefinitionMap.put("/v2/api-docs", "anon"); + filterChainDefinitionMap.put("/v2/api-docs-ext", "anon"); + filterChainDefinitionMap.put("*.html", "anon"); + filterChainDefinitionMap.put("/static/**", "anon"); + filterChainDefinitionMap.put("/webjars/**", "anon"); + filterChainDefinitionMap.put("/druid/**", "anon"); + filterChainDefinitionMap.put("/favicon.ico", "anon"); + filterChainDefinitionMap.put("/captcha.jpg", "anon"); + filterChainDefinitionMap.put("/csrf", "anon"); + //文件上传可直接访问 + filterChainDefinitionMap.put(fileUploadProperties.getAccessUrl(), "anon"); + filterChainDefinitionMap.put("/images/**", "anon"); + filterChainDefinitionMap.put("/js/**", "anon"); + filterChainDefinitionMap.put("/layui/**", "anon"); + filterChainDefinitionMap.put("/css/**", "anon"); + filterChainDefinitionMap.put("/layui-ext/**", "anon"); + filterChainDefinitionMap.put("/app/api/**", "anon");*/ + // 所有请求经过过滤器 + filterChainDefinitionMap.put("/**", "authc,token"); + shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return shiroFilterFactoryBean; } -*/ /** * 开启shiro aop注解支持. * 使用代理方式;所以需要开启代码支持; * - * @return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor*//* + * @return org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor*/ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { @@ -121,4 +182,3 @@ public class ShiroConfig { } -*/ diff --git a/src/main/java/com/huoran/iasf/common/utils/Constant.java b/src/main/java/com/huoran/iasf/common/utils/Constant.java index a85f09f..c7027f0 100644 --- a/src/main/java/com/huoran/iasf/common/utils/Constant.java +++ b/src/main/java/com/huoran/iasf/common/utils/Constant.java @@ -77,4 +77,9 @@ public class Constant { public static final Integer NAVIGATION_MENU_VISIBLE = 0; public static final Integer THE_NAVIGATION_MENU_IS_NOT_VISIBLE = 1; + + /** + * 异常处理 controller request url + */ + public static final String ERROR_CONTROLLER_PATH = "/error/throw"; } diff --git a/src/main/java/com/huoran/iasf/controller/DeptController.java b/src/main/java/com/huoran/iasf/controller/DeptController.java index 6d41c22..1bc7204 100644 --- a/src/main/java/com/huoran/iasf/controller/DeptController.java +++ b/src/main/java/com/huoran/iasf/controller/DeptController.java @@ -71,7 +71,7 @@ public class DeptController { @GetMapping("/dept/{id}") @ApiOperation(value = "查询组织详情接口") @LogAnnotation(title = "机构管理", action = "查询组织详情") - @RequiresPermissions("sys:dept:detail") +// @RequiresPermissions("sys:dept:detail") public R detailInfo(@PathVariable("id") String id) { return R.success(deptService.getById(id)); } @@ -79,7 +79,7 @@ public class DeptController { @GetMapping("/dept/tree") @ApiOperation(value = "树型组织列表接口",response = DeptRespNodeVO.class) @LogAnnotation(title = "部门管理", action = "树型组织列表") - @RequiresPermissions(value = {"sys:user:list", "sys:user:update", "sys:user:add", "sys:dept:add", "sys:dept:update"}, logical = Logical.OR) +// @RequiresPermissions(value = {"sys:user:list", "sys:user:update", "sys:user:add", "sys:dept:add", "sys:dept:update"}, logical = Logical.OR) public R getTree( @ApiParam(name = "deptId", value = "部门id",required = false) @RequestParam(required = false) String deptId) { diff --git a/src/main/java/com/huoran/iasf/controller/ExceptionController.java b/src/main/java/com/huoran/iasf/controller/ExceptionController.java new file mode 100644 index 0000000..ae52aa6 --- /dev/null +++ b/src/main/java/com/huoran/iasf/controller/ExceptionController.java @@ -0,0 +1,24 @@ +package com.huoran.iasf.controller; + +import com.huoran.iasf.common.exception.BusinessException; +import com.huoran.iasf.common.utils.Constant; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +/** + * 过滤器异常控制器 + */ +@RestController +public class ExceptionController { + + @RequestMapping(Constant.ERROR_CONTROLLER_PATH) + @ResponseStatus(HttpStatus.UNAUTHORIZED) + public void handleException(HttpServletRequest request){ + throw (BusinessException) request.getAttribute("filterError"); + } +} + diff --git a/src/main/java/com/huoran/iasf/controller/PermissionController.java b/src/main/java/com/huoran/iasf/controller/PermissionController.java index 50adb8e..7a371db 100644 --- a/src/main/java/com/huoran/iasf/controller/PermissionController.java +++ b/src/main/java/com/huoran/iasf/controller/PermissionController.java @@ -53,7 +53,7 @@ public class PermissionController { @GetMapping("/permission/tree/all") @ApiOperation(value = "获取所有目录菜单树接口") @LogAnnotation(title = "菜单权限管理", action = "获取所有目录菜单树") - @RequiresPermissions(value = {"sys:role:update", "sys:role:add"}, logical = Logical.OR) +// @RequiresPermissions(value = {"sys:role:update", "sys:role:add"}, logical = Logical.OR) public R getAllPermissionTree() { return R.success(permissionService.selectAllByTree()); } diff --git a/src/main/java/com/huoran/iasf/controller/RoleController.java b/src/main/java/com/huoran/iasf/controller/RoleController.java index 94c37a3..3db30bf 100644 --- a/src/main/java/com/huoran/iasf/controller/RoleController.java +++ b/src/main/java/com/huoran/iasf/controller/RoleController.java @@ -94,7 +94,7 @@ public class RoleController { @GetMapping("/role/{id}") @ApiOperation(value = "查询角色详情接口") @LogAnnotation(title = "角色管理", action = "查询角色详情") - @RequiresPermissions("sys:role:detail") +// @RequiresPermissions("sys:role:detail") public R detailInfo(@PathVariable("id") String id) { // return R.success(roleService.detailInfo(id)); SysRole role = roleService.getById(id); diff --git a/src/main/java/com/huoran/iasf/controller/RolePermissionController.java b/src/main/java/com/huoran/iasf/controller/RolePermissionController.java index 46d5f4e..367cf45 100644 --- a/src/main/java/com/huoran/iasf/controller/RolePermissionController.java +++ b/src/main/java/com/huoran/iasf/controller/RolePermissionController.java @@ -33,7 +33,7 @@ public class RolePermissionController { @PostMapping("/role/permission") @ApiOperation(value = "修改或者新增角色菜单权限接口") @LogAnnotation(title = "角色和菜单关联接口", action = "修改或者新增角色菜单权限") - @RequiresPermissions(value = {"sys:role:update", "sys:role:add"}, logical = Logical.OR) +// @RequiresPermissions(value = {"sys:role:update", "sys:role:add"}, logical = Logical.OR) public R operationRolePermission(@RequestBody @Valid RolePermissionOperationReqVO vo) { rolePermissionService.addRolePermission(vo); return R.success(); diff --git a/src/main/java/com/huoran/iasf/controller/SiteController.java b/src/main/java/com/huoran/iasf/controller/SiteController.java index 1c02372..e032178 100644 --- a/src/main/java/com/huoran/iasf/controller/SiteController.java +++ b/src/main/java/com/huoran/iasf/controller/SiteController.java @@ -35,9 +35,9 @@ public class SiteController { private SiteService siteService; @PostMapping("/add") - @ApiOperation(value = "新增站点") - @LogAnnotation(title = "站点管理", action = "新增站点") - @RequiresPermissions("sys:site:add") +// @ApiOperation(value = "新增站点") +// @LogAnnotation(title = "站点管理", action = "新增站点") +// @RequiresPermissions("sys:site:add") public R addUserGroup(@RequestBody Site site) { Site one = siteService.getOne(new QueryWrapper(). eq("site_name", site.getSiteName())); @@ -49,18 +49,18 @@ public class SiteController { } @DeleteMapping("/delete/{id}") - @ApiOperation(value = "删除站点") - @LogAnnotation(title = "站点管理", action = "删除站点") - @RequiresPermissions("sys:site:deleted") +// @ApiOperation(value = "删除站点") +// @LogAnnotation(title = "站点管理", action = "删除站点") +// @RequiresPermissions("sys:site:deleted") public R deleted(@PathVariable("id") Integer id) { siteService.removeById(id); return R.success(); } @PutMapping("/update") - @ApiOperation(value = "更新站点") - @LogAnnotation(title = "站点管理", action = "更新站点") - @RequiresPermissions("sys:site:update") +// @ApiOperation(value = "更新站点") +// @LogAnnotation(title = "站点管理", action = "更新站点") +// @RequiresPermissions("sys:site:update") public R updateUserGroup(@RequestBody Site site) { if (StringUtils.isEmpty(site.getId())) { return R.fail("id不能为空"); diff --git a/src/main/java/com/huoran/iasf/controller/SysLogController.java b/src/main/java/com/huoran/iasf/controller/SysLogController.java index 39d5344..644d524 100644 --- a/src/main/java/com/huoran/iasf/controller/SysLogController.java +++ b/src/main/java/com/huoran/iasf/controller/SysLogController.java @@ -1,4 +1,3 @@ -/* package com.huoran.iasf.controller; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -16,14 +15,13 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; -*/ /** * 系统操作日志 * * @author cheney * @version V1.0 * @date 2022年7月28日 - *//* + */ @RequestMapping("/sys") @Api(tags = "系统模块-系统操作日志管理") @@ -35,7 +33,7 @@ public class SysLogController { @PostMapping("/logs") @ApiOperation(value = "分页查询系统操作日志接口") @LogAnnotation(title = "系统操作日志管理", action = "分页查询系统操作日志") - @RequiresPermissions("sys:log:list") +// @RequiresPermissions("sys:log:list") public R pageInfo(@RequestBody SysLog vo) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); if (!StringUtils.isEmpty(vo.getUsername())) { @@ -57,10 +55,9 @@ public class SysLogController { @DeleteMapping("/logs") @ApiOperation(value = "删除日志接口") @LogAnnotation(title = "系统操作日志管理", action = "删除系统操作日志") - @RequiresPermissions("sys:log:deleted") +// @RequiresPermissions("sys:log:deleted") public R deleted(@RequestBody List logIds) { logService.removeByIds(logIds); return R.success(); } } -*/ diff --git a/src/main/java/com/huoran/iasf/controller/UserController.java b/src/main/java/com/huoran/iasf/controller/UserController.java index da03ce9..1568088 100644 --- a/src/main/java/com/huoran/iasf/controller/UserController.java +++ b/src/main/java/com/huoran/iasf/controller/UserController.java @@ -64,7 +64,7 @@ public class UserController { @PutMapping("/user") @ApiOperation(value = "更新用户信息接口") @LogAnnotation(title = "用户管理", action = "更新用户信息") - @RequiresPermissions("sys:user:update") +// @RequiresPermissions("sys:user:update") public R updateUserInfo(@RequestBody SysUser vo) { if (StringUtils.isEmpty(vo.getId())) { return R.fail("id不能为空"); @@ -76,7 +76,7 @@ public class UserController { @GetMapping("/user/{id}") @ApiOperation(value = "查询用户详情接口") @LogAnnotation(title = "用户管理", action = "查询用户详情") - @RequiresPermissions("sys:user:detail") +// @RequiresPermissions("sys:user:detail") public R detailInfo(@PathVariable("id") String id) { UserListResp userResp = userService.detailInfo(id); return R.success(userResp); @@ -84,7 +84,7 @@ public class UserController { @PostMapping("/users") @ApiOperation(value = "分页获取用户列表接口") - @RequiresPermissions("sys:user:list") +// @RequiresPermissions("sys:user:list") @LogAnnotation(title = "用户管理", action = "分页获取用户列表") public R pageInfo(@RequestBody UserListReq userListReq) { return userService.pageInfo(userListReq); @@ -92,7 +92,7 @@ public class UserController { @PostMapping("/user") @ApiOperation(value = "新增用户接口") - @RequiresPermissions("sys:user:add") +// @RequiresPermissions("sys:user:add") @LogAnnotation(title = "用户管理", action = "新增用户") public R addUser(@RequestBody @Valid SysUser vo) { userService.addUser(vo); @@ -171,7 +171,7 @@ public class UserController { @DeleteMapping("/user") @ApiOperation(value = "删除用户接口") @LogAnnotation(title = "用户管理", action = "删除用户") - @RequiresPermissions("sys:user:deleted") +// @RequiresPermissions("sys:user:deleted") public R deletedUser(@RequestBody @ApiParam(value = "用户id集合") List userIds) { //删除用户, 删除redis的绑定的角色跟权限 httpSessionService.abortUserByUserIds(userIds); diff --git a/src/main/java/com/huoran/iasf/controller/UserDeptController.java b/src/main/java/com/huoran/iasf/controller/UserDeptController.java index 6e48f6a..f270c59 100644 --- a/src/main/java/com/huoran/iasf/controller/UserDeptController.java +++ b/src/main/java/com/huoran/iasf/controller/UserDeptController.java @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RestController; * @since 2022-08-15 */ @RestController -@RequestMapping("//user-dept") +@RequestMapping("/userDept") public class UserDeptController { } diff --git a/src/main/java/com/huoran/iasf/service/HttpApiSessionService.java b/src/main/java/com/huoran/iasf/service/HttpApiSessionService.java index e8b6a9d..ffc408b 100644 --- a/src/main/java/com/huoran/iasf/service/HttpApiSessionService.java +++ b/src/main/java/com/huoran/iasf/service/HttpApiSessionService.java @@ -13,7 +13,7 @@ import java.util.Date; * session管理器 * @author cheney * @version V1.0 - * @date 2020年5月11日 + * @date 2022年5月11日 */ @Service public class HttpApiSessionService { @@ -25,7 +25,7 @@ public class HttpApiSessionService { public static final String SUBJECT = "HuoRan_SUBJECT"; - public static final long EXPIRE = 1000 * 60 * 60 * 24 * 2; //过期时间,毫秒,一天 + public static final long EXPIRE = 1000 * 60 * 60 * 24; //过期时间,毫秒,一天 //秘钥 public static final String APP_SECRET = "HuoRan_SYMMETRIC_ENCRYPTION_HS256"; @@ -38,7 +38,7 @@ public class HttpApiSessionService { * @param userId username * @return token */ - public String geneJsonWebToken(String userId, String userName) { + public String generateToken(Integer userId, String userName) { String token = Jwts.builder().setSubject(SUBJECT) .claim(USER_ID_KEY, userId) .claim(USER_USERNAME_KEY, userName) diff --git a/src/main/java/com/huoran/iasf/service/HttpSessionService.java b/src/main/java/com/huoran/iasf/service/HttpSessionService.java index 703b563..58dd00e 100644 --- a/src/main/java/com/huoran/iasf/service/HttpSessionService.java +++ b/src/main/java/com/huoran/iasf/service/HttpSessionService.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.huoran.iasf.common.utils.Constant; import com.huoran.iasf.entity.SysUser; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -28,8 +29,7 @@ public class HttpSessionService { private RedisService redisService; @Resource private UserRoleService userRoleService; - @Resource - private RolePermissionService rolePermissionService; + @Resource private HttpServletRequest request; @Resource @@ -45,12 +45,17 @@ public class HttpSessionService { @Value("${spring.redis.key.prefix.permissionRefresh}") private String redisPermissionRefreshKey; + @Value("${spring.redis.key.expire.permissionRefresh}") private Long redisPermissionRefreshExpire; + @Autowired + private HttpApiSessionService sessionService; + public String createTokenAndUser(SysUser user, List roles, Set permissions) { + String token = sessionService.generateToken(user.getId(), user.getUsername()); //方便根据id找到redis的key, 修改密码/退出登陆 方便使用 - String token = getRandomToken() + "#" + user.getId(); +// String token = getRandomToken() + "#" + user.getId(); JSONObject sessionInfo = new JSONObject(); sessionInfo.put(Constant.USERID_KEY, user.getId()); sessionInfo.put(Constant.USERNAME_KEY, user.getUsername()); diff --git a/src/main/java/com/huoran/iasf/service/impl/UserServiceImpl.java b/src/main/java/com/huoran/iasf/service/impl/UserServiceImpl.java index 10af37e..1667e57 100644 --- a/src/main/java/com/huoran/iasf/service/impl/UserServiceImpl.java +++ b/src/main/java/com/huoran/iasf/service/impl/UserServiceImpl.java @@ -194,7 +194,7 @@ public class UserServiceImpl extends ServiceImpl impleme } if (StringUtils.isNotEmpty(vo.getPhone())) { - vo.setEmail(vo.getPhone()); + vo.setPhone(vo.getPhone()); } //更新部门 @@ -239,7 +239,7 @@ public class UserServiceImpl extends ServiceImpl impleme public R resetPwd(String userId) { SysUser sysUser = baseMapper.selectById(userId); sysUser.setSalt(PasswordUtils.getSalt()); - String encode = PasswordUtils.encode("1122aa", sysUser.getSalt()); + String encode = PasswordUtils.encode("111aaa", sysUser.getSalt()); sysUser.setPassword(encode); int update = baseMapper.updateById(sysUser); return update>0 ? R.success("重置成功") : R.fail("重置失败"); @@ -261,7 +261,7 @@ public class UserServiceImpl extends ServiceImpl impleme public void addUser(SysUser vo) { vo.setSalt(PasswordUtils.getSalt()); - String encode = PasswordUtils.encode("1122aa", vo.getSalt()); + String encode = PasswordUtils.encode("111aaa", vo.getSalt()); vo.setPassword(encode); vo.setStatus(1); vo.setCreateWhere(1); @@ -380,7 +380,7 @@ public class UserServiceImpl extends ServiceImpl impleme errMsg += countNum + "必填项:(姓名不能为空)"; ret = false; } else { - vo1.setUserName(realName); + vo1.setRealName(realName); } //检验账号 if ("".equals(username)) { @@ -471,6 +471,11 @@ public class UserServiceImpl extends ServiceImpl impleme int insert = userGroupMapper.insert(userGroup); groupId=userGroup.getId(); } + }else { + ++countNum; + vo1.setGroupName(groupName + " *必填项:(用户组不能为空)"); + errMsg += countNum + " *必填项:(用户组不能为空)"; + ret = false; } if (!"".equals(getPhone)) { @@ -600,7 +605,7 @@ public class UserServiceImpl extends ServiceImpl impleme if (0==usernameId){ SysUser vo = new SysUser(); vo.setSalt(PasswordUtils.getSalt()); - String encode = PasswordUtils.encode("1122aa", vo.getSalt()); + String encode = PasswordUtils.encode("111aaa", vo.getSalt()); vo.setRealName(realName); vo.setPhone(getPhone); vo.setJobNumber(jobNumber); diff --git a/src/main/resources/whiteList.properties b/src/main/resources/whiteList.properties deleted file mode 100644 index 0bfd774..0000000 --- a/src/main/resources/whiteList.properties +++ /dev/null @@ -1,2 +0,0 @@ -whiteList=/iasf/sys/user/login,\ - /iasf/sys/exportFailure \ No newline at end of file