修改了security权限控制,优化了附件sdk异常处理

This commit is contained in:
ajaxfan
2021-03-12 15:02:20 +08:00
parent 0d86bc88ec
commit 6fbfd5de6e
10 changed files with 105 additions and 232 deletions

View File

@ -41,7 +41,7 @@ public class ModelConvertor {
* @return * @return
*/ */
public Optional<AttachmentEntity> toAttachmentEntity(String json) { public Optional<AttachmentEntity> toAttachmentEntity(String json) {
return Optional.of(json).map(content -> { return Optional.ofNullable(json).map(content -> {
AttachmentEntity entity = null; AttachmentEntity entity = null;
try { try {
@ -49,7 +49,8 @@ public class ModelConvertor {
log.debug("convert to model: {}", vo); log.debug("convert to model: {}", vo);
entity = new AttachmentEntity(); entity = new AttachmentEntity();
entity.setId(vo.getFileId()).setFilename(vo.getOriginalName()).setBid(vo.getObjectId()); entity.setId(vo.getFileId()).setFilename(vo.getOriginalName()).setBid(vo.getObjectId())
.setKey(vo.getFileName());
} catch (JsonProcessingException e) { } catch (JsonProcessingException e) {
log.error(json); log.error(json);
log.error(e.getMessage()); log.error(e.getMessage());
@ -139,8 +140,8 @@ public class ModelConvertor {
*/ */
private SysStorageVO tpDownPO(String json) throws JsonMappingException, JsonProcessingException { private SysStorageVO tpDownPO(String json) throws JsonMappingException, JsonProcessingException {
log.debug("current convertor json is: {}", json); log.debug("current convertor json is: {}", json);
return Optional.ofNullable(objectMapper.readValue(json, DownStream.class)) return Optional.ofNullable(objectMapper.readValue(json, DownStream.class)).map(ds -> ds.getData())
.map(ds -> ds.getData().getSysStorageVO()).orElseGet(SysStorageVO::new); .map(data -> data.getSysStorageVO()).orElseGet(SysStorageVO::new);
} }
/** /**

View File

@ -1,46 +0,0 @@
package com.chinaunicom.ebtp.mall.cloud.attachment.sdk.fallback;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.AttachmentDetail;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.AttachmentEntity;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.FeedbackMessage;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.Snowflake;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.param.QueryParameter;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.service.QueryService;
@Component
public class QueryServiceFallback implements QueryService {
@Override
public Snowflake getSnokflakId() {
return null;
}
@Override
public AttachmentEntity getObjectDetail(String oid) {
return null;
}
@Override
public AttachmentDetail getAttachmentDetails(QueryParameter param) {
return null;
}
@Override
public FeedbackMessage handleFileUpload(String businessId, MultipartFile file) {
return null;
}
@Override
public byte[] downloadByBid(String bid) {
return null;
}
@Override
public byte[] downloadByOid(String oid) {
return null;
}
}

View File

@ -1,43 +0,0 @@
package com.chinaunicom.ebtp.mall.cloud.attachment.sdk.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.config.FeignSupportConfig;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.fallback.QueryServiceFallback;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.AttachmentDetail;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.AttachmentEntity;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.FeedbackMessage;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.model.Snowflake;
import com.chinaunicom.ebtp.mall.cloud.attachment.sdk.param.QueryParameter;
@FeignClient(value = "core-service-ebtp-updownload", configuration = FeignSupportConfig.class, fallback = QueryServiceFallback.class)
public interface QueryService {
@RequestMapping(method = RequestMethod.GET, value = "v1/business/id")
Snowflake getSnokflakId();
@RequestMapping(method = RequestMethod.GET, value = "v1/attachment/find/oid/{oid}")
AttachmentEntity getObjectDetail(@PathVariable("oid") String oid);
@RequestMapping(method = RequestMethod.POST, value = "v1/attachment/find")
AttachmentDetail getAttachmentDetails(@RequestBody QueryParameter param);
@RequestMapping(value = "/v1/attachment/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
FeedbackMessage handleFileUpload(@RequestPart(value = "businessId") String businessId,
@RequestPart(value = "file") MultipartFile file);
@GetMapping("/v1/attachment/download/bid/{bid}")
byte[] downloadByBid(@PathVariable("bid") String bid);
@GetMapping("/v1/attachment/download/oid/{oid}")
byte[] downloadByOid(@PathVariable("oid") String oid);
}

View File

@ -7,14 +7,17 @@ public class SysStorageVO {
/* 文件原始名称 */ /* 文件原始名称 */
private String originalName; private String originalName;
/* 附件id */ /* 附件id */
private String fileId; private String fileId;
/* 业务id */ /* 业务id */
private String objectId; private String objectId;
/* 文件流 */ /* 文件流 */
private byte[] fileStream; private byte[] fileStream;
/* 文件唯一标识 */
private String fileName;
} }

View File

@ -1,16 +1,14 @@
package com.chinaunicom.mall.ebtp.cloud.security.starter.config; 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.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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.chinaunicom.mall.ebtp.cloud.security.starter.filter.TokenAuthenticationFilter;
/** /**
* 安全设置 * 安全设置
* *
@ -20,9 +18,6 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true, securedEnabled = true)
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailService userDetailsService;
@Bean @Bean
public TokenAuthenticationFilter authenticationTokenFilterBean() { public TokenAuthenticationFilter authenticationTokenFilterBean() {
return new TokenAuthenticationFilter(); return new TokenAuthenticationFilter();
@ -39,9 +34,5 @@ public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
http.csrf().disable(); http.csrf().disable();
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class); http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
} }
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
} }

View File

@ -3,18 +3,13 @@ package com.chinaunicom.mall.ebtp.cloud.security.starter.entity;
import java.util.List; import java.util.List;
import lombok.Data; import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
@Data @Data
public class AuthorityEntity implements GrantedAuthority { public class AuthorityEntity {
private String roleName; private String roleName;
private String roleCode; private String roleCode;
private String roleId; private String roleId;
private List<String> authorities; private List<String> authorities;
@Override
public String getAuthority() {
return roleCode;
}
} }

View File

@ -0,0 +1,23 @@
package com.chinaunicom.mall.ebtp.cloud.security.starter.entity;
import org.springframework.security.core.GrantedAuthority;
import lombok.AllArgsConstructor;
/**
* 基于角色的权限信息
*
* @author Ajaxfan
*/
@AllArgsConstructor
public class RoleCodeAuthority implements GrantedAuthority {
private static final long serialVersionUID = -7881153326775335008L;
private String roleCode;
@Override
public String getAuthority() {
return roleCode;
}
}

View File

@ -1,13 +1,10 @@
package com.chinaunicom.mall.ebtp.cloud.security.starter.entity; package com.chinaunicom.mall.ebtp.cloud.security.starter.entity;
import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import lombok.Data; import lombok.Data;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
/** /**
* 缓存用户实体映射类 * 缓存用户实体映射类
@ -18,7 +15,7 @@ import org.springframework.security.core.userdetails.UserDetails;
*/ */
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
public class SecurityUser implements UserDetails { public class SecurityUser {
/** /**
* PKID * PKID
@ -162,38 +159,4 @@ public class SecurityUser implements UserDetails {
*/ */
private List<AuthorityEntity> authorityList; private List<AuthorityEntity> authorityList;
@Override
public Collection<? extends GrantedAuthority> 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;
}
} }

View File

@ -1,19 +0,0 @@
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;
}
}

View File

@ -1,9 +1,16 @@
package com.chinaunicom.mall.ebtp.cloud.security.starter.filter; package com.chinaunicom.mall.ebtp.cloud.security.starter.filter;
import com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants; import java.io.IOException;
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.AuthorityEntity; import java.util.Arrays;
import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.SecurityUser; import java.util.Collections;
import lombok.extern.slf4j.Slf4j; import java.util.List;
import java.util.Optional;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.RegExUtils; import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -18,15 +25,11 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain; import com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants;
import javax.servlet.ServletException; import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.RoleCodeAuthority;
import javax.servlet.http.HttpServletRequest; import com.chinaunicom.mall.ebtp.cloud.security.starter.entity.SecurityUser;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
/** /**
* 请求Token拦截 * 请求Token拦截
@ -36,60 +39,62 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
public class TokenAuthenticationFilter extends OncePerRequestFilter { public class TokenAuthenticationFilter extends OncePerRequestFilter {
private @Autowired RestTemplate restTemplate; private @Autowired RestTemplate restTemplate;
private @Value("${user.auth.resource.userinfo}") String token_uri; private @Value("${user.auth.resource.userinfo}") String token_uri;
/** /**
* @param request * @param request
* @param response * @param response
* @param filterChain * @param filterChain
* @throws ServletException * @throws ServletException
* @throws IOException * @throws IOException
*/ */
@Override @Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException { final FilterChain filterChain) throws ServletException, IOException {
// 清空上下文中的缓存信息, 防止二次请求时数据异常 (如此, 每次有新的请求进入都会进行token的验证) // 清空上下文中的缓存信息, 防止二次请求时数据异常 (如此, 每次有新的请求进入都会进行token的验证)
SecurityContextHolder.getContext().setAuthentication(null); SecurityContextHolder.getContext().setAuthentication(null);
// 提取request头信息 // 提取request头信息
final String header = request.getHeader(Constants.AUTHORIZATION_HEADER); final String header = request.getHeader(Constants.AUTHORIZATION_HEADER);
final String currentRoleCode = request.getHeader(Constants.CURRENT_ROLE_CODE); final String currentRoleCode = request.getHeader(Constants.CURRENT_ROLE_CODE);
// 检查请求头是否包含 Bearer 前缀 // 检查请求头是否包含 Bearer 前缀
if (StringUtils.startsWith(header, Constants.TOKEN_PREFIX)) { if (StringUtils.startsWith(header, Constants.TOKEN_PREFIX)) {
// 移除header的前缀提取出token字串 // 移除header的前缀提取出token字串
String authToken = RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, ""); String authToken = RegExUtils.replaceAll(header, Constants.TOKEN_PREFIX, "");
try {// 通过token读取用户信息 (新增用户当前角色字段: 2021-03-05) try {// 通过token读取用户信息 (新增用户当前角色字段: 2021-03-05)
SecurityContextHolder.getContext().setAuthentication(getAuthentication(authToken, currentRoleCode)); SecurityContextHolder.getContext().setAuthentication(getAuthentication(authToken, currentRoleCode));
} catch (Exception e) { } catch (Exception e) {
log.error(e.getMessage()); log.error(e.getMessage());
} }
} }
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
} }
/** /**
* 调用山分的认证中心接口获取该token的绑定信息 * 调用山分的认证中心接口获取该token的绑定信息
* *
* @param token * @param token
* @return * @return
*/ */
private Authentication getAuthentication(final String token, final String currentRoleCode) { private Authentication getAuthentication(final String token, final String currentRoleCode) {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
// 设置安全头 // 设置安全头
headers.add(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", token)); headers.add(HttpHeaders.AUTHORIZATION, String.format("Bearer %s", token));
ResponseEntity<SecurityUser> entity = restTemplate.exchange(token_uri, HttpMethod.GET, ResponseEntity<SecurityUser> entity = restTemplate.exchange(token_uri, HttpMethod.GET,
new HttpEntity<String>(headers), SecurityUser.class); new HttpEntity<String>(headers), SecurityUser.class);
SecurityUser securityUser = entity.getBody(); SecurityUser securityUser = entity.getBody();
//设置当前角色的权限
List<AuthorityEntity> authority = Optional.ofNullable(currentRoleCode) // 根据当前角色设定权限列表
.map(o -> securityUser.getAuthorityList().stream().filter(f -> Objects.equals(f.getRoleCode(), currentRoleCode)).collect(Collectors.toList())) List<RoleCodeAuthority> authorities = Optional.ofNullable(currentRoleCode)
.orElse(securityUser.getAuthorityList()); .map(o -> Arrays.asList(new RoleCodeAuthority(o))).orElse(Collections.emptyList());
return new UsernamePasswordAuthenticationToken(securityUser.setCurrentRoleCode(currentRoleCode), token, authority);
} return new UsernamePasswordAuthenticationToken(securityUser.setCurrentRoleCode(currentRoleCode), token,
authorities);
}
} }