From 526aeb11258e4f3475208eba783b3c1bb3222c76 Mon Sep 17 00:00:00 2001 From: macro Date: Tue, 5 Nov 2019 16:09:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0mall-security=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=EF=BC=8C=E6=95=B4=E5=90=88=E4=BA=86JWT+SpringSecurity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mall-admin/pom.xml | 12 +- .../macro/mall/config/MallSecurityConfig.java | 29 ++++ .../com/macro/mall/config/SecurityConfig.java | 124 ------------------ .../macro/mall/service/UmsAdminService.java | 6 + .../service/impl/UmsAdminServiceImpl.java | 31 +++-- mall-admin/src/main/resources/application.yml | 17 ++- .../mall/demo/config/Swagger2Config.java | 3 +- mall-portal/pom.xml | 8 +- .../component/GoAccessDeniedHandler.java | 23 ---- .../component/GoAuthenticationEntryPoint.java | 23 ---- .../GoAuthenticationFailureHandler.java | 23 ---- .../GoAuthenticationSuccessHandler.java | 23 ---- .../component/GoLogoutSuccessHandler.java | 23 ---- .../portal/config/MallSecurityConfig.java | 29 ++++ .../mall/portal/config/SecurityConfig.java | 113 ---------------- .../mall/portal/config/Swagger2Config.java | 49 ++++++- .../controller/UmsMemberController.java | 23 +++- .../mall/portal/service/UmsMemberService.java | 11 ++ .../service/impl/UmsMemberServiceImpl.java | 42 +++++- .../src/main/resources/application.yml | 20 +++ mall-security/.gitignore | 31 +++++ mall-security/pom.xml | 38 ++++++ .../JwtAuthenticationTokenFilter.java | 5 +- .../RestAuthenticationEntryPoint.java | 3 +- .../component/RestfulAccessDeniedHandler.java | 3 +- .../security/config/IgnoreUrlsConfig.java | 22 ++++ .../mall/security/config/SecurityConfig.java | 99 ++++++++++++++ .../mall/security}/util/JwtTokenUtil.java | 26 ++-- pom.xml | 8 ++ 29 files changed, 460 insertions(+), 407 deletions(-) create mode 100644 mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java delete mode 100644 mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/component/GoAccessDeniedHandler.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationEntryPoint.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationFailureHandler.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationSuccessHandler.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/component/GoLogoutSuccessHandler.java create mode 100644 mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java delete mode 100644 mall-portal/src/main/java/com/macro/mall/portal/config/SecurityConfig.java create mode 100644 mall-security/.gitignore create mode 100644 mall-security/pom.xml rename {mall-admin/src/main/java/com/macro/mall => mall-security/src/main/java/com/macro/mall/security}/component/JwtAuthenticationTokenFilter.java (95%) rename {mall-admin/src/main/java/com/macro/mall => mall-security/src/main/java/com/macro/mall/security}/component/RestAuthenticationEntryPoint.java (95%) rename {mall-admin/src/main/java/com/macro/mall => mall-security/src/main/java/com/macro/mall/security}/component/RestfulAccessDeniedHandler.java (95%) create mode 100644 mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java create mode 100644 mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java rename {mall-admin/src/main/java/com/macro/mall => mall-security/src/main/java/com/macro/mall/security}/util/JwtTokenUtil.java (85%) diff --git a/mall-admin/pom.xml b/mall-admin/pom.xml index f2dd777..153fa81 100644 --- a/mall-admin/pom.xml +++ b/mall-admin/pom.xml @@ -29,12 +29,8 @@ mall-mbg - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-security + com.macro.mall + mall-security org.springframework.cloud @@ -44,10 +40,6 @@ org.springframework.cloud spring-cloud-starter-config - - io.jsonwebtoken - jjwt - com.aliyun.oss aliyun-sdk-oss diff --git a/mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java b/mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java new file mode 100644 index 0000000..336ffd2 --- /dev/null +++ b/mall-admin/src/main/java/com/macro/mall/config/MallSecurityConfig.java @@ -0,0 +1,29 @@ +package com.macro.mall.config; + +import com.macro.mall.security.config.SecurityConfig; +import com.macro.mall.service.UmsAdminService; +import org.springframework.beans.factory.annotation.Autowired; +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.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * mall-security模块相关配置 + * Created by macro on 2019/11/5. + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled=true) +public class MallSecurityConfig extends SecurityConfig { + + @Autowired + private UmsAdminService adminService; + + @Bean + public UserDetailsService userDetailsService() { + //获取登录用户信息 + return username -> adminService.loadUserByUsername(username); + } +} diff --git a/mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java b/mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java deleted file mode 100644 index 2ff5559..0000000 --- a/mall-admin/src/main/java/com/macro/mall/config/SecurityConfig.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.macro.mall.config; - -import com.macro.mall.bo.AdminUserDetails; -import com.macro.mall.component.JwtAuthenticationTokenFilter; -import com.macro.mall.component.RestAuthenticationEntryPoint; -import com.macro.mall.component.RestfulAccessDeniedHandler; -import com.macro.mall.model.UmsAdmin; -import com.macro.mall.model.UmsPermission; -import com.macro.mall.service.UmsAdminService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -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.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import org.springframework.web.cors.CorsConfiguration; -import org.springframework.web.cors.UrlBasedCorsConfigurationSource; -import org.springframework.web.filter.CorsFilter; - -import java.util.List; - - -/** - * SpringSecurity的配置 - * Created by macro on 2018/4/26. - */ -@Configuration -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled=true) -public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - private UmsAdminService adminService; - @Autowired - private RestfulAccessDeniedHandler restfulAccessDeniedHandler; - @Autowired - private RestAuthenticationEntryPoint restAuthenticationEntryPoint; - - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { - httpSecurity.csrf()// 由于使用的是JWT,我们这里不需要csrf - .disable() - .sessionManagement()// 基于token,所以不需要session - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authorizeRequests() - .antMatchers(HttpMethod.GET, // 允许对于网站静态资源的无授权访问 - "/", - "/*.html", - "/favicon.ico", - "/**/*.html", - "/**/*.css", - "/**/*.js", - "/swagger-resources/**", - "/v2/api-docs/**", - "/webjars/springfox-swagger-ui/**" - ) - .permitAll() - .antMatchers("/admin/login", "/admin/register")// 对登录注册要允许匿名访问 - .permitAll() - .antMatchers(HttpMethod.OPTIONS)//跨域请求会先进行一次options请求 - .permitAll() - .antMatchers("/actuator/**")// 允许SpringBoot Admin 访问监控信息 - .permitAll() -// .antMatchers("/**")//测试时全部运行访问 -// .permitAll() - .anyRequest()// 除上面外的所有请求全部需要鉴权认证 - .authenticated(); - // 禁用缓存 - httpSecurity.headers().cacheControl(); - // 添加JWT filter - httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); - //添加自定义未授权和未登录结果返回 - httpSecurity.exceptionHandling() - .accessDeniedHandler(restfulAccessDeniedHandler) - .authenticationEntryPoint(restAuthenticationEntryPoint); - } - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsService()) - .passwordEncoder(passwordEncoder()); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Bean - public UserDetailsService userDetailsService() { - //获取登录用户信息 - return username -> { - UmsAdmin admin = adminService.getAdminByUsername(username); - if (admin != null) { - List permissionList = adminService.getPermissionList(admin.getId()); - return new AdminUserDetails(admin,permissionList); - } - throw new UsernameNotFoundException("用户名或密码错误"); - }; - } - - @Bean - public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){ - return new JwtAuthenticationTokenFilter(); - } - - @Bean - @Override - public AuthenticationManager authenticationManagerBean() throws Exception { - return super.authenticationManagerBean(); - } - -} diff --git a/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java index 870149d..32b2ab7 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java +++ b/mall-admin/src/main/java/com/macro/mall/service/UmsAdminService.java @@ -4,6 +4,7 @@ import com.macro.mall.dto.UmsAdminParam; import com.macro.mall.model.UmsAdmin; import com.macro.mall.model.UmsPermission; import com.macro.mall.model.UmsRole; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.transaction.annotation.Transactional; import java.util.List; @@ -78,4 +79,9 @@ public interface UmsAdminService { * 获取用户所有权限(包括角色权限和+-权限) */ List getPermissionList(Long adminId); + + /** + * 获取用户信息 + */ + UserDetails loadUserByUsername(String username); } diff --git a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java index 1d0121b..309c68d 100644 --- a/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java +++ b/mall-admin/src/main/java/com/macro/mall/service/impl/UmsAdminServiceImpl.java @@ -1,6 +1,7 @@ package com.macro.mall.service.impl; import com.github.pagehelper.PageHelper; +import com.macro.mall.bo.AdminUserDetails; import com.macro.mall.dao.UmsAdminPermissionRelationDao; import com.macro.mall.dao.UmsAdminRoleRelationDao; import com.macro.mall.dto.UmsAdminParam; @@ -9,20 +10,18 @@ import com.macro.mall.mapper.UmsAdminMapper; import com.macro.mall.mapper.UmsAdminPermissionRelationMapper; import com.macro.mall.mapper.UmsAdminRoleRelationMapper; import com.macro.mall.model.*; +import com.macro.mall.security.util.JwtTokenUtil; import com.macro.mall.service.UmsAdminService; -import com.macro.mall.util.JwtTokenUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -44,15 +43,9 @@ import java.util.stream.Collectors; public class UmsAdminServiceImpl implements UmsAdminService { private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class); @Autowired - private AuthenticationManager authenticationManager; - @Autowired - private UserDetailsService userDetailsService; - @Autowired private JwtTokenUtil jwtTokenUtil; @Autowired private PasswordEncoder passwordEncoder; - @Value("${jwt.tokenHead}") - private String tokenHead; @Autowired private UmsAdminMapper adminMapper; @Autowired @@ -102,7 +95,7 @@ public class UmsAdminServiceImpl implements UmsAdminService { String token = null; //密码需要客户端加密后传递 try { - UserDetails userDetails = userDetailsService.loadUserByUsername(username); + UserDetails userDetails = loadUserByUsername(username); if(!passwordEncoder.matches(password,userDetails.getPassword())){ throw new BadCredentialsException("密码不正确"); } @@ -145,11 +138,7 @@ public class UmsAdminServiceImpl implements UmsAdminService { @Override public String refreshToken(String oldToken) { - String token = oldToken.substring(tokenHead.length()); - if (jwtTokenUtil.canRefresh(token)) { - return jwtTokenUtil.refreshToken(token); - } - return null; + return jwtTokenUtil.refreshHeadToken(oldToken); } @Override @@ -249,4 +238,14 @@ public class UmsAdminServiceImpl implements UmsAdminService { public List getPermissionList(Long adminId) { return adminRoleRelationDao.getPermissionList(adminId); } + + public UserDetails loadUserByUsername(String username){ + //获取用户信息 + UmsAdmin admin = getAdminByUsername(username); + if (admin != null) { + List permissionList = getPermissionList(admin.getId()); + return new AdminUserDetails(admin,permissionList); + } + throw new UsernameNotFoundException("用户名或密码错误"); + } } diff --git a/mall-admin/src/main/resources/application.yml b/mall-admin/src/main/resources/application.yml index 7c11d58..1515031 100644 --- a/mall-admin/src/main/resources/application.yml +++ b/mall-admin/src/main/resources/application.yml @@ -33,9 +33,24 @@ management: #开启SpringBoot Admin的监控 show-details: always jwt: tokenHeader: Authorization #JWT存储的请求头 - secret: mySecret #JWT加解密使用的密钥 + secret: mall-admin-secret #JWT加解密使用的密钥 expiration: 604800 #JWT的超期限时间(60*60*24) tokenHead: Bearer #JWT负载中拿到开头 +ignored: #安全路径白名单 + urls: + - /swagger-ui.html + - /swagger-resources/** + - /swagger/** + - /**/v2/api-docs + - /**/*.js + - /**/*.css + - /**/*.png + - /**/*.ico + - /webjars/springfox-swagger-ui/** + - /actuator/** + - /druid/** + - /admin/login + - /admin/register aliyun: oss: endpoint: oss-cn-shenzhen.aliyuncs.com # oss对外服务的访问域名 diff --git a/mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java b/mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java index cf7069b..22b0fe4 100644 --- a/mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java +++ b/mall-demo/src/main/java/com/macro/mall/demo/config/Swagger2Config.java @@ -55,7 +55,8 @@ public class Swagger2Config { private List securityContexts() { //设置需要登录认证的路径 List result = new ArrayList<>(); - result.add(getContextByPath("/feign/admin/brand.*")); + result.add(getContextByPath("/feign/admin/getBrandList")); + result.add(getContextByPath("/feign/portal/cartList")); return result; } diff --git a/mall-portal/pom.xml b/mall-portal/pom.xml index 96a0fa3..084b6ec 100644 --- a/mall-portal/pom.xml +++ b/mall-portal/pom.xml @@ -30,12 +30,8 @@ mall-mbg - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-security + com.macro.mall + mall-security diff --git a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAccessDeniedHandler.java b/mall-portal/src/main/java/com/macro/mall/portal/component/GoAccessDeniedHandler.java deleted file mode 100644 index 103eab9..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAccessDeniedHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.macro.mall.portal.component; - -import cn.hutool.json.JSONUtil; -import com.macro.mall.common.api.CommonResult; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Created by macro on 2018/8/6. - */ -public class GoAccessDeniedHandler implements AccessDeniedHandler{ - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { - response.setHeader("Content-Type", "application/json;charset=utf-8"); - response.getWriter().print(JSONUtil.parse(CommonResult.forbidden(accessDeniedException.getMessage()))); - response.getWriter().flush(); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationEntryPoint.java b/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationEntryPoint.java deleted file mode 100644 index 7da2442..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationEntryPoint.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.macro.mall.portal.component; - -import cn.hutool.json.JSONUtil; -import com.macro.mall.common.api.CommonResult; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Created by macro on 2018/8/6. - */ -public class GoAuthenticationEntryPoint implements AuthenticationEntryPoint { - @Override - public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { - response.setHeader("Content-Type", "application/json;charset=utf-8"); - response.getWriter().print(JSONUtil.parse(CommonResult.unauthorized(authException.getMessage()))); - response.getWriter().flush(); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationFailureHandler.java b/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationFailureHandler.java deleted file mode 100644 index 2f338e8..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationFailureHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.macro.mall.portal.component; - -import cn.hutool.json.JSONUtil; -import com.macro.mall.common.api.CommonResult; -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; - -/** - * Created by macro on 2018/8/6. - */ -public class GoAuthenticationFailureHandler implements AuthenticationFailureHandler { - @Override - public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - response.setHeader("Content-Type", "application/json;charset=utf-8"); - response.getWriter().print(JSONUtil.parse(CommonResult.failed("登录失败,用户名或密码错误!"))); - response.getWriter().flush(); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationSuccessHandler.java b/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationSuccessHandler.java deleted file mode 100644 index c3f6c7c..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/component/GoAuthenticationSuccessHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.macro.mall.portal.component; - -import cn.hutool.json.JSONUtil; -import com.macro.mall.common.api.CommonResult; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.AuthenticationSuccessHandler; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Created by macro on 2018/8/6. - */ -public class GoAuthenticationSuccessHandler implements AuthenticationSuccessHandler { - @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - response.setHeader("Content-Type", "application/json;charset=utf-8"); - response.getWriter().print(JSONUtil.parse(CommonResult.success(null,"登录成功"))); - response.getWriter().flush(); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/component/GoLogoutSuccessHandler.java b/mall-portal/src/main/java/com/macro/mall/portal/component/GoLogoutSuccessHandler.java deleted file mode 100644 index 13ec6fc..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/component/GoLogoutSuccessHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.macro.mall.portal.component; - -import cn.hutool.json.JSONUtil; -import com.macro.mall.common.api.CommonResult; -import org.springframework.security.core.Authentication; -import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -/** - * Created by macro on 2018/8/6. - */ -public class GoLogoutSuccessHandler implements LogoutSuccessHandler { - @Override - public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { - response.setHeader("Content-Type", "application/json;charset=utf-8"); - response.getWriter().print(JSONUtil.parse(CommonResult.success(null,"已注销"))); - response.getWriter().flush(); - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java b/mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java new file mode 100644 index 0000000..456cc18 --- /dev/null +++ b/mall-portal/src/main/java/com/macro/mall/portal/config/MallSecurityConfig.java @@ -0,0 +1,29 @@ +package com.macro.mall.portal.config; + +import com.macro.mall.portal.service.UmsMemberService; +import com.macro.mall.security.config.SecurityConfig; +import org.springframework.beans.factory.annotation.Autowired; +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.configuration.EnableWebSecurity; +import org.springframework.security.core.userdetails.UserDetailsService; + +/** + * mall-security模块相关配置 + * Created by macro on 2019/11/5. + */ +@Configuration +@EnableWebSecurity +@EnableGlobalMethodSecurity(prePostEnabled=true) +public class MallSecurityConfig extends SecurityConfig { + + @Autowired + private UmsMemberService memberService; + + @Bean + public UserDetailsService userDetailsService() { + //获取登录用户信息 + return username -> memberService.loadUserByUsername(username); + } +} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/config/SecurityConfig.java b/mall-portal/src/main/java/com/macro/mall/portal/config/SecurityConfig.java deleted file mode 100644 index 574b06a..0000000 --- a/mall-portal/src/main/java/com/macro/mall/portal/config/SecurityConfig.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.macro.mall.portal.config; - -import com.macro.mall.model.UmsMember; -import com.macro.mall.portal.component.*; -import com.macro.mall.portal.domain.MemberDetails; -import com.macro.mall.portal.service.UmsMemberService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; - -/** - * SpringSecurity的配置 - * Created by macro on 2018/8/3. - */ -@Configuration -@EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - private UmsMemberService memberService; - @Override - protected void configure(HttpSecurity http) throws Exception { - http.authorizeRequests() - .antMatchers(HttpMethod.GET, // 允许对于网站静态资源的无授权访问 - "/", - "/*.html", - "/favicon.ico", - "/**/*.html", - "/**/*.css", - "/**/*.js", - "/swagger-resources/**", - "/v2/api-docs/**", - "/webjars/springfox-swagger-ui/**" - ) - .permitAll() - .antMatchers(HttpMethod.OPTIONS)//跨域请求会先进行一次options请求 - .permitAll() - .antMatchers( - "/sso/*",//登录注册 - "/home/**"//首页接口 - ) - .permitAll() - .antMatchers("/member/**","/returnApply/**")// 测试时开启 - .permitAll() - .antMatchers("/actuator/**")// 允许SpringBoot Admin 访问监控信息 - .permitAll() - .anyRequest()// 除上面外的所有请求全部需要鉴权认证 - .authenticated() - .and() - .exceptionHandling() - .accessDeniedHandler(new GoAccessDeniedHandler()) - .authenticationEntryPoint(new GoAuthenticationEntryPoint()) - .and() - .formLogin() - .loginPage("/sso/login") - .successHandler(new GoAuthenticationSuccessHandler()) - .failureHandler(new GoAuthenticationFailureHandler()) - .and() - .logout() - .logoutUrl("/sso/logout") - .logoutSuccessHandler(new GoLogoutSuccessHandler()) - .invalidateHttpSession(true) - .deleteCookies("JSESSIONID") -// .and() -// .requiresChannel() -// .antMatchers("/sso/*") -// .requiresSecure() -// .anyRequest() -// .requiresInsecure() -// .and() -// .rememberMe() -// .tokenValiditySeconds(1800) -// .key("token_key") - .and() - .csrf() - .disable();//开启basic认证登录后可以调用需要认证的接口 - } - - @Override - protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsService()) - .passwordEncoder(passwordEncoder()); - } - - @Bean - public PasswordEncoder passwordEncoder() { - return new BCryptPasswordEncoder(); - } - - @Bean - public UserDetailsService userDetailsService() { - //获取登录用户信息 - return new UserDetailsService() { - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - UmsMember member = memberService.getByUsername(username); - if(member!=null){ - return new MemberDetails(member); - } - throw new UsernameNotFoundException("用户名或密码错误"); - } - }; - } -} diff --git a/mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java b/mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java index 8d053aa..0a62e84 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/config/Swagger2Config.java @@ -6,10 +6,17 @@ import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.AuthorizationScope; +import springfox.documentation.service.SecurityReference; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import java.util.ArrayList; +import java.util.List; + /** * Swagger2API文档的配置 * Created by macro on 2018/4/26. @@ -18,21 +25,57 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; @EnableSwagger2 public class Swagger2Config { @Bean - public Docket createRestApi(){ + public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.macro.mall.portal.controller")) .paths(PathSelectors.any()) - .build(); + .build() + .securitySchemes(securitySchemes()) + .securityContexts(securityContexts()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("mall前台系统") - .description("mall前台系统") + .description("mall前台模块") .contact("macro") .version("1.0") .build(); } + + private List securitySchemes() { + //设置请求头信息 + List result = new ArrayList<>(); + ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header"); + result.add(apiKey); + return result; + } + + private List securityContexts() { + //设置需要登录认证的路径 + List result = new ArrayList<>(); + result.add(getContextByPath("/member/.*")); + result.add(getContextByPath("/cart/.*")); + result.add(getContextByPath("/order/.*")); + result.add(getContextByPath("/returnApply/.*")); + return result; + } + + private SecurityContext getContextByPath(String pathRegex) { + return SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex(pathRegex)) + .build(); + } + + private List defaultAuth() { + List result = new ArrayList<>(); + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + result.add(new SecurityReference("Authorization", authorizationScopes)); + return result; + } } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java index 655b9f9..5fdb856 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/controller/UmsMemberController.java @@ -5,12 +5,16 @@ import com.macro.mall.portal.service.UmsMemberService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; +import java.util.HashMap; +import java.util.Map; + /** * 会员登录注册管理Controller * Created by macro on 2018/8/3. @@ -19,10 +23,12 @@ import org.springframework.web.bind.annotation.ResponseBody; @Api(tags = "UmsMemberController", description = "会员登录注册管理") @RequestMapping("/sso") public class UmsMemberController { + @Value("${jwt.tokenHead}") + private String tokenHead; @Autowired private UmsMemberService memberService; - @ApiOperation("注册") + @ApiOperation("会员注册") @RequestMapping(value = "/register", method = RequestMethod.POST) @ResponseBody public CommonResult register(@RequestParam String username, @@ -32,6 +38,21 @@ public class UmsMemberController { return memberService.register(username, password, telephone, authCode); } + @ApiOperation("会员登录") + @RequestMapping(value = "/login", method = RequestMethod.POST) + @ResponseBody + public CommonResult login(@RequestParam String username, + @RequestParam String password) { + String token = memberService.login(username, password); + if (token == null) { + return CommonResult.validateFailed("用户名或密码错误"); + } + Map tokenMap = new HashMap<>(); + tokenMap.put("token", token); + tokenMap.put("tokenHead", tokenHead); + return CommonResult.success(tokenMap); + } + @ApiOperation("获取验证码") @RequestMapping(value = "/getAuthCode", method = RequestMethod.GET) @ResponseBody diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java index 4a10e4d..a31da1b 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/UmsMemberService.java @@ -2,6 +2,7 @@ package com.macro.mall.portal.service; import com.macro.mall.common.api.CommonResult; import com.macro.mall.model.UmsMember; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.transaction.annotation.Transactional; /** @@ -45,4 +46,14 @@ public interface UmsMemberService { * 根据会员id修改会员积分 */ void updateIntegration(Long id,Integer integration); + + /** + * 获取用户信息 + */ + UserDetails loadUserByUsername(String username); + + /** + * 登录后获取token + */ + String login(String username, String password); } diff --git a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java index 99d4f59..0f46bd0 100644 --- a/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java +++ b/mall-portal/src/main/java/com/macro/mall/portal/service/impl/UmsMemberServiceImpl.java @@ -10,11 +10,19 @@ import com.macro.mall.model.UmsMemberLevelExample; import com.macro.mall.portal.domain.MemberDetails; import com.macro.mall.portal.service.RedisService; import com.macro.mall.portal.service.UmsMemberService; +import com.macro.mall.security.util.JwtTokenUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; @@ -30,13 +38,16 @@ import java.util.Random; */ @Service public class UmsMemberServiceImpl implements UmsMemberService { + private static final Logger LOGGER = LoggerFactory.getLogger(UmsMemberServiceImpl.class); + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private JwtTokenUtil jwtTokenUtil; @Autowired private UmsMemberMapper memberMapper; @Autowired private UmsMemberLevelMapper memberLevelMapper; @Autowired - private PasswordEncoder passwordEncoder; - @Autowired private RedisService redisService; @Value("${redis.key.prefix.authCode}") private String REDIS_KEY_PREFIX_AUTH_CODE; @@ -139,6 +150,33 @@ public class UmsMemberServiceImpl implements UmsMemberService { memberMapper.updateByPrimaryKeySelective(record); } + @Override + public UserDetails loadUserByUsername(String username) { + UmsMember member = getByUsername(username); + if(member!=null){ + return new MemberDetails(member); + } + throw new UsernameNotFoundException("用户名或密码错误"); + } + + @Override + public String login(String username, String password) { + String token = null; + //密码需要客户端加密后传递 + try { + UserDetails userDetails = loadUserByUsername(username); + if(!passwordEncoder.matches(password,userDetails.getPassword())){ + throw new BadCredentialsException("密码不正确"); + } + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + token = jwtTokenUtil.generateToken(userDetails); + } catch (AuthenticationException e) { + LOGGER.warn("登录异常:{}", e.getMessage()); + } + return token; + } + //对输入的验证码进行校验 private boolean verifyAuthCode(String authCode, String telephone){ if(StringUtils.isEmpty(authCode)){ diff --git a/mall-portal/src/main/resources/application.yml b/mall-portal/src/main/resources/application.yml index e2e060e..1850c5e 100644 --- a/mall-portal/src/main/resources/application.yml +++ b/mall-portal/src/main/resources/application.yml @@ -50,6 +50,26 @@ management: #开启SpringBoot Admin的监控 endpoint: health: show-details: always +jwt: + tokenHeader: Authorization #JWT存储的请求头 + secret: mall-portal-secret #JWT加解密使用的密钥 + expiration: 604800 #JWT的超期限时间(60*60*24) + tokenHead: Bearer #JWT负载中拿到开头 +ignored: #安全路径白名单 + urls: + - /swagger-ui.html + - /swagger-resources/** + - /swagger/** + - /**/v2/api-docs + - /**/*.js + - /**/*.css + - /**/*.png + - /**/*.ico + - /webjars/springfox-swagger-ui/** + - /druid/** + - /actuator/** + - /sso/** + - /home/** # 自定义redis键值 redis: key: diff --git a/mall-security/.gitignore b/mall-security/.gitignore new file mode 100644 index 0000000..a2a3040 --- /dev/null +++ b/mall-security/.gitignore @@ -0,0 +1,31 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ diff --git a/mall-security/pom.xml b/mall-security/pom.xml new file mode 100644 index 0000000..1ed891e --- /dev/null +++ b/mall-security/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + com.macro.mall + mall-security + 1.0-SNAPSHOT + jar + + mall-security + mall-security project for mall + + + com.macro.mall + mall + 1.0-SNAPSHOT + + + + + com.macro.mall + mall-common + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-security + + + io.jsonwebtoken + jjwt + + + + diff --git a/mall-admin/src/main/java/com/macro/mall/component/JwtAuthenticationTokenFilter.java b/mall-security/src/main/java/com/macro/mall/security/component/JwtAuthenticationTokenFilter.java similarity index 95% rename from mall-admin/src/main/java/com/macro/mall/component/JwtAuthenticationTokenFilter.java rename to mall-security/src/main/java/com/macro/mall/security/component/JwtAuthenticationTokenFilter.java index fe13f52..bddd916 100644 --- a/mall-admin/src/main/java/com/macro/mall/component/JwtAuthenticationTokenFilter.java +++ b/mall-security/src/main/java/com/macro/mall/security/component/JwtAuthenticationTokenFilter.java @@ -1,6 +1,6 @@ -package com.macro.mall.component; +package com.macro.mall.security.component; -import com.macro.mall.util.JwtTokenUtil; +import com.macro.mall.security.util.JwtTokenUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -10,7 +10,6 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; diff --git a/mall-admin/src/main/java/com/macro/mall/component/RestAuthenticationEntryPoint.java b/mall-security/src/main/java/com/macro/mall/security/component/RestAuthenticationEntryPoint.java similarity index 95% rename from mall-admin/src/main/java/com/macro/mall/component/RestAuthenticationEntryPoint.java rename to mall-security/src/main/java/com/macro/mall/security/component/RestAuthenticationEntryPoint.java index 6a107ed..a0b370c 100644 --- a/mall-admin/src/main/java/com/macro/mall/component/RestAuthenticationEntryPoint.java +++ b/mall-security/src/main/java/com/macro/mall/security/component/RestAuthenticationEntryPoint.java @@ -1,4 +1,4 @@ -package com.macro.mall.component; +package com.macro.mall.security.component; import cn.hutool.json.JSONUtil; import com.macro.mall.common.api.CommonResult; @@ -15,7 +15,6 @@ import java.io.IOException; * 当未登录或者token失效访问接口时,自定义的返回结果 * Created by macro on 2018/5/14. */ -@Component public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { diff --git a/mall-admin/src/main/java/com/macro/mall/component/RestfulAccessDeniedHandler.java b/mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java similarity index 95% rename from mall-admin/src/main/java/com/macro/mall/component/RestfulAccessDeniedHandler.java rename to mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java index 8b22012..b885449 100644 --- a/mall-admin/src/main/java/com/macro/mall/component/RestfulAccessDeniedHandler.java +++ b/mall-security/src/main/java/com/macro/mall/security/component/RestfulAccessDeniedHandler.java @@ -1,4 +1,4 @@ -package com.macro.mall.component; +package com.macro.mall.security.component; import cn.hutool.json.JSONUtil; import com.macro.mall.common.api.CommonResult; @@ -15,7 +15,6 @@ import java.io.IOException; * 当访问接口没有权限时,自定义的返回结果 * Created by macro on 2018/4/26. */ -@Component public class RestfulAccessDeniedHandler implements AccessDeniedHandler{ @Override public void handle(HttpServletRequest request, diff --git a/mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java b/mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java new file mode 100644 index 0000000..0dc852a --- /dev/null +++ b/mall-security/src/main/java/com/macro/mall/security/config/IgnoreUrlsConfig.java @@ -0,0 +1,22 @@ +package com.macro.mall.security.config; + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用于配置不需要保护的资源路径 + * Created by macro on 2018/11/5. + */ +@Getter +@Setter +@ConfigurationProperties(prefix = "ignored") +public class IgnoreUrlsConfig { + + private List urls = new ArrayList<>(); + +} diff --git a/mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java b/mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java new file mode 100644 index 0000000..6fea681 --- /dev/null +++ b/mall-security/src/main/java/com/macro/mall/security/config/SecurityConfig.java @@ -0,0 +1,99 @@ +package com.macro.mall.security.config; + +import com.macro.mall.security.component.JwtAuthenticationTokenFilter; +import com.macro.mall.security.component.RestAuthenticationEntryPoint; +import com.macro.mall.security.component.RestfulAccessDeniedHandler; +import com.macro.mall.security.util.JwtTokenUtil; +import org.springframework.context.annotation.Bean; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + + +/** + * 对SpringSecurity的配置的扩展,支持自定义白名单资源路径和查询用户逻辑 + * Created by macro on 2019/11/5. + */ +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity httpSecurity) throws Exception { + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity + .authorizeRequests(); + for (String url : ignoreUrlsConfig().getUrls()) { + registry.antMatchers(url).permitAll(); + } + //允许跨域请求的OPTIONS请求 + registry.antMatchers(HttpMethod.OPTIONS) + .permitAll(); + // 任何请求需要身份认证 + registry.and() + .authorizeRequests() + .anyRequest() + .authenticated() + // 关闭跨站请求防护及不使用session + .and() + .csrf() + .disable() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + // 自定义权限拒绝处理类 + .and() + .exceptionHandling() + .accessDeniedHandler(restfulAccessDeniedHandler()) + .authenticationEntryPoint(restAuthenticationEntryPoint()) + // 自定义权限拦截器JWT过滤器 + .and() + .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService()) + .passwordEncoder(passwordEncoder()); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() { + return new JwtAuthenticationTokenFilter(); + } + + @Bean + @Override + public AuthenticationManager authenticationManagerBean() throws Exception { + return super.authenticationManagerBean(); + } + + @Bean + public RestfulAccessDeniedHandler restfulAccessDeniedHandler() { + return new RestfulAccessDeniedHandler(); + } + + @Bean + public RestAuthenticationEntryPoint restAuthenticationEntryPoint() { + return new RestAuthenticationEntryPoint(); + } + + @Bean + public IgnoreUrlsConfig ignoreUrlsConfig() { + return new IgnoreUrlsConfig(); + } + + @Bean + public JwtTokenUtil jwtTokenUtil() { + return new JwtTokenUtil(); + } + +} diff --git a/mall-admin/src/main/java/com/macro/mall/util/JwtTokenUtil.java b/mall-security/src/main/java/com/macro/mall/security/util/JwtTokenUtil.java similarity index 85% rename from mall-admin/src/main/java/com/macro/mall/util/JwtTokenUtil.java rename to mall-security/src/main/java/com/macro/mall/security/util/JwtTokenUtil.java index 15bcbf1..336cfe5 100644 --- a/mall-admin/src/main/java/com/macro/mall/util/JwtTokenUtil.java +++ b/mall-security/src/main/java/com/macro/mall/security/util/JwtTokenUtil.java @@ -1,6 +1,8 @@ -package com.macro.mall.util; +package com.macro.mall.security.util; -import io.jsonwebtoken.*; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -22,7 +24,7 @@ import java.util.Map; * HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret) * Created by macro on 2018/4/26. */ -@Component +//@Component public class JwtTokenUtil { private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class); private static final String CLAIM_KEY_USERNAME = "sub"; @@ -31,6 +33,8 @@ public class JwtTokenUtil { private String secret; @Value("${jwt.expiration}") private Long expiration; + @Value("${jwt.tokenHead}") + private String tokenHead; /** * 根据负责生成JWT的token @@ -124,12 +128,18 @@ public class JwtTokenUtil { return !isTokenExpired(token); } + /** - * 刷新token + * 当原来的token没过期是可以刷新 + * @param oldToken 带tokenHead的token */ - public String refreshToken(String token) { - Claims claims = getClaimsFromToken(token); - claims.put(CLAIM_KEY_CREATED, new Date()); - return generateToken(claims); + public String refreshHeadToken(String oldToken) { + String token = oldToken.substring(tokenHead.length()); + if (canRefresh(token)) { + Claims claims = getClaimsFromToken(token); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + return null; } } diff --git a/pom.xml b/pom.xml index f26f278..1bf3c84 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ mall-common mall-mbg + mall-security mall-demo mall-admin mall-search @@ -47,6 +48,7 @@ 2.1.5 1.0-SNAPSHOT 1.0-SNAPSHOT + 1.0-SNAPSHOT @@ -87,6 +89,12 @@ mall-mbg ${mall-mbg.version} + + + com.macro.mall + mall-security + ${mall-security.version} + com.github.pagehelper