From 0d86bc88ecd909bf073857959b8a77caecec6da9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=98=E5=BA=86=E5=90=89?= <51312040@qq.com> Date: Wed, 10 Mar 2021 10:40:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../starter/config/BrowserSecurityConfig.java | 45 ++++--- .../starter/entity/AuthorityEntity.java | 7 +- .../security/starter/entity/SecurityUser.java | 39 +++++- .../filter/CustomUserDetailService.java | 19 +++ .../filter/TokenAuthenticationFilter.java | 117 ++++++++++-------- 5 files changed, 152 insertions(+), 75 deletions(-) create mode 100644 mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/CustomUserDetailService.java diff --git a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/config/BrowserSecurityConfig.java b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/config/BrowserSecurityConfig.java index cb6a8d7..400c072 100644 --- a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/config/BrowserSecurityConfig.java +++ b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/config/BrowserSecurityConfig.java @@ -1,38 +1,47 @@ package com.chinaunicom.mall.ebtp.cloud.security.starter.config; +import com.chinaunicom.mall.ebtp.cloud.security.starter.filter.CustomUserDetailService; +import com.chinaunicom.mall.ebtp.cloud.security.starter.filter.TokenAuthenticationFilter; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +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.web.authentication.UsernamePasswordAuthenticationFilter; -import com.chinaunicom.mall.ebtp.cloud.security.starter.filter.TokenAuthenticationFilter; - /** * 安全设置 - * + * * @author Ajaxfan */ @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true) public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { - @Bean - public TokenAuthenticationFilter authenticationTokenFilterBean() { - return new TokenAuthenticationFilter(); - } + @Autowired + private CustomUserDetailService userDetailsService; - /** - * 向Filter链中插入自定义TokenFilter - * - * @param http - * @throws Exception - */ - @Override - protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable(); - http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); - } + @Bean + public TokenAuthenticationFilter authenticationTokenFilterBean() { + return new TokenAuthenticationFilter(); + } + /** + * 向Filter链中插入自定义TokenFilter + * + * @param http + * @throws Exception + */ + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable(); + http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService); + } } diff --git a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/AuthorityEntity.java b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/AuthorityEntity.java index c664703..0ec0bcd 100644 --- a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/AuthorityEntity.java +++ b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/AuthorityEntity.java @@ -3,13 +3,18 @@ package com.chinaunicom.mall.ebtp.cloud.security.starter.entity; import java.util.List; import lombok.Data; +import org.springframework.security.core.GrantedAuthority; @Data -public class AuthorityEntity { +public class AuthorityEntity implements GrantedAuthority { private String roleName; private String roleCode; private String roleId; private List authorities; + @Override + public String getAuthority() { + return roleCode; + } } diff --git a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/SecurityUser.java b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/SecurityUser.java index 41732ef..80a0855 100644 --- a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/SecurityUser.java +++ b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/entity/SecurityUser.java @@ -1,10 +1,13 @@ package com.chinaunicom.mall.ebtp.cloud.security.starter.entity; +import java.util.Collection; import java.util.Date; import java.util.List; import lombok.Data; import lombok.experimental.Accessors; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; /** * 缓存用户实体映射类 @@ -15,7 +18,7 @@ import lombok.experimental.Accessors; */ @Data @Accessors(chain = true) -public class SecurityUser { +public class SecurityUser implements UserDetails { /** * PKID @@ -159,4 +162,38 @@ public class SecurityUser { */ private List authorityList; + @Override + public Collection getAuthorities() { + return authorityList; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return fullName; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } } diff --git a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/CustomUserDetailService.java b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/CustomUserDetailService.java new file mode 100644 index 0000000..917a1fc --- /dev/null +++ b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/CustomUserDetailService.java @@ -0,0 +1,19 @@ +package com.chinaunicom.mall.ebtp.cloud.security.starter.filter; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; + +@Service +@Slf4j +public class CustomUserDetailService implements UserDetailsService { + + + @Override + public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { + log.info("UserDetails -------------------------------- {} ---------------------------------------", s); + return null; + } +} diff --git a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java index 1abf366..53c7202 100644 --- a/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java +++ b/mall-ebtp-cloud-security-starter/src/main/java/com/chinaunicom/mall/ebtp/cloud/security/starter/filter/TokenAuthenticationFilter.java @@ -1,12 +1,9 @@ package com.chinaunicom.mall.ebtp.cloud.security.starter.filter; -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants; +import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthorityEntity; +import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.SecurityUser; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -21,68 +18,78 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.client.RestTemplate; import org.springframework.web.filter.OncePerRequestFilter; -import com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants; -import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.SecurityUser; - -import lombok.extern.slf4j.Slf4j; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; /** * 请求Token拦截 - * + * * @author Ajaxfan */ @Slf4j public class TokenAuthenticationFilter extends OncePerRequestFilter { - private @Autowired RestTemplate restTemplate; - private @Value("${user.auth.resource.userinfo}") String token_uri; + private @Autowired RestTemplate restTemplate; + private @Value("${user.auth.resource.userinfo}") String token_uri; - /** - * @param request - * @param response - * @param filterChain - * @throws ServletException - * @throws IOException - */ - @Override - protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, - final FilterChain filterChain) throws ServletException, IOException { - // 清空上下文中的缓存信息, 防止二次请求时数据异常 (如此, 每次有新的请求进入,都会进行token的验证) - SecurityContextHolder.getContext().setAuthentication(null); + /** + * @param request + * @param response + * @param filterChain + * @throws ServletException + * @throws IOException + */ + @Override + protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, + final FilterChain filterChain) throws ServletException, IOException { + // 清空上下文中的缓存信息, 防止二次请求时数据异常 (如此, 每次有新的请求进入,都会进行token的验证) + SecurityContextHolder.getContext().setAuthentication(null); - // 提取request头信息 - final String header = request.getHeader(Constants.AUTHORIZATION_HEADER); - final String currentRoleCode = request.getHeader(Constants.CURRENT_ROLE_CODE); + // 提取request头信息 + final String header = request.getHeader(Constants.AUTHORIZATION_HEADER); + final String currentRoleCode = request.getHeader(Constants.CURRENT_ROLE_CODE); - // 检查请求头是否包含 Bearer 前缀 - if (StringUtils.startsWith(header, Constants.TOKEN_PREFIX)) { - // 移除header的前缀,提取出token字串 - String authToken = RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, ""); + // 检查请求头是否包含 Bearer 前缀 + if (StringUtils.startsWith(header, Constants.TOKEN_PREFIX)) { + // 移除header的前缀,提取出token字串 + String authToken = RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, ""); - try {// 通过token读取用户信息 (新增用户当前角色字段: 2021-03-05) - SecurityContextHolder.getContext().setAuthentication(getAuthentication(authToken, currentRoleCode)); - } catch (Exception e) { - log.error(e.getMessage()); - } - } - filterChain.doFilter(request, response); - } + try {// 通过token读取用户信息 (新增用户当前角色字段: 2021-03-05) + SecurityContextHolder.getContext().setAuthentication(getAuthentication(authToken, currentRoleCode)); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + filterChain.doFilter(request, response); + } - /** - * 调用山分的认证中心接口,获取该token的绑定信息 - * - * @param token - * @return - */ - private Authentication getAuthentication(final String token, final String currentRoleCode) { - HttpHeaders headers = new HttpHeaders(); - // 设置安全头 - headers.add(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", token)); + /** + * 调用山分的认证中心接口,获取该token的绑定信息 + * + * @param token + * @return + */ + private Authentication getAuthentication(final String token, final String currentRoleCode) { + HttpHeaders headers = new HttpHeaders(); + // 设置安全头 + headers.add(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", token)); - ResponseEntity entity = restTemplate.exchange(token_uri, HttpMethod.GET, - new HttpEntity(headers), SecurityUser.class); + ResponseEntity entity = restTemplate.exchange(token_uri, HttpMethod.GET, + new HttpEntity(headers), SecurityUser.class); - return new UsernamePasswordAuthenticationToken(entity.getBody().setCurrentRoleCode(currentRoleCode), token); - } + SecurityUser securityUser = entity.getBody(); + //设置当前角色的权限 + List authority = Optional.ofNullable(currentRoleCode) + .map(o -> securityUser.getAuthorityList().stream().filter(f -> Objects.equals(f.getRoleCode(), currentRoleCode)).collect(Collectors.toList())) + .orElse(securityUser.getAuthorityList()); + return new UsernamePasswordAuthenticationToken(securityUser.setCurrentRoleCode(currentRoleCode), token, authority); + } }