由于项目使用 spring cloud + oauth2 +reids 来认证,每次微服务中需要自己手动代码获取登录用户信息比较麻烦,所以想到统一通过 filter 来实现
步骤如下:
1.定义操作人基本信息接口
IBaseOperator.java
import java.util.Date; /** * 基础操作人信息 */ public interface IBaseOperator { void setOperatedByUserName(String operatedByUserName); String getOperatedByUserName(); void setOperatedOn(Date operatedOn); Date getOperatedOn(); }
IOperator.java
package com.dimpt.common.interfaces; /** * 操作人信息 */ public interface IOperator extends IBaseOperator { void setOperatedByUserId(String operatedByUserId); String getOperatedByUserId(); void setOperatedByRealName(String operatedByRealName); String getOperatedByRealName(); }
2.拦截器
OperaterFilter.java
import java.io.IOException; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import com.dimpt.common.http.BodyRequestWrapper; import com.dimpt.common.http.ParameterRequestWrapper; import com.dimpt.common.interfaces.IOperator; import com.dimpt.common.security.CustomerUser; import com.dimpt.common.util.JsonUtils; import com.dimpt.common.util.components.UserUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; /** * @RequestBody 注解参数中新增 {@link IOperator} 数据 */ @Component public class OperaterFilter implements Filter { private static final Logger logger = LoggerFactory.getLogger(OperaterFilter.class); @Autowired UserUtils userUtils; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; CustomerUser customerUser = userUtils.getCustomerUser(); if (customerUser != null) { CustomerUser.User user = customerUser.getUserDetails(); //region 设置 ServletRequest 的登录用户参数 HashMap m = new HashMap(httpServletRequest.getParameterMap()); m.put("operatedByUserId",user.getUserId()); m.put("operatedByUserName",user.getUserName()); m.put("operatedByRealName",user.getName()); m.put("operatedOn",new Date()); ParameterRequestWrapper parameterRequestWrapper = new ParameterRequestWrapper(httpServletRequest, m); httpServletRequest = parameterRequestWrapper; //endregion //设置 @RequestBody 的登录用户数据 BodyRequestWrapper bodyReaderHttpServletRequestWrapper = new BodyRequestWrapper(httpServletRequest); String bodyString = bodyReaderHttpServletRequestWrapper.getBodyString(); if(!StringUtils.isEmpty(bodyString)) { Map bodyMap = JsonUtils.toMap(bodyString); bodyMap.put("operatedByUserId",user.getUserId()); bodyMap.put("operatedByUserName",user.getUserName()); bodyMap.put("operatedByRealName",user.getName()); bodyMap.put("operatedOn",new Date()); String newBodyString = JsonUtils.toString(bodyMap); bodyReaderHttpServletRequestWrapper.setBodyString(newBodyString); httpServletRequest = bodyReaderHttpServletRequestWrapper; } } filterChain.doFilter(httpServletRequest, servletResponse); } @Override public void destroy() { } }
BodyRequestWrapper.java
import java.io.*; import java.nio.charset.Charset; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * @RequestBody 参数的 HttpServletRequestWrapper */ @SuppressWarnings("unchecked") public class BodyRequestWrapper extends HttpServletRequestWrapper{ private byte[] body; private String bodyString; public byte[] getBody() { return body; } public String getBodyString() { return bodyString; } public BodyRequestWrapper(HttpServletRequest request) throws IOException { super(request); bodyString = getBodyString(request); body = bodyString.getBytes(Charset.forName("UTF-8")); } /** * 获取请求Body * * @param request * @return */ public String getBodyString(final ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = cloneInputStream(request.getInputStream());//将获取到的请求参数重新塞入request里面去 reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); String line = ""; while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (reader != null) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } return sb.toString(); } public void setBodyString(String bodyString) throws UnsupportedEncodingException { bodyString=bodyString; this.body = bodyString.getBytes("UTF-8"); } /** * Description: 复制输入流</br> * * @param inputStream * @return</br> */ public InputStream cloneInputStream(ServletInputStream inputStream) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; try { while ((len = inputStream.read(buffer)) > -1) { byteArrayOutputStream.write(buffer, 0, len); } byteArrayOutputStream.flush(); } catch (IOException e) { e.printStackTrace(); } InputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); return byteArrayInputStream; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException { return bais.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } }; } }
ParameterRequestWrapper.java
import java.util.Enumeration; import java.util.Map; import java.util.Vector; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * HttpServletRequest 参数的 HttpServletRequestWrapper */ @SuppressWarnings("unchecked") public class ParameterRequestWrapper extends HttpServletRequestWrapper { private Map params; public ParameterRequestWrapper(HttpServletRequest request, Map newParams) { super(request); this.params = newParams; } public Map getParameterMap() { return params; } public Enumeration getParameterNames() { Vector l = new Vector(params.keySet()); return l.elements(); } public String[] getParameterValues(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String[]) { return (String[])v; } else if (v instanceof String) { return new String[] {(String)v}; } else { return new String[] {v.toString()}; } } public String getParameter(String name) { Object v = params.get(name); if (v == null) { return null; } else if (v instanceof String[]) { String[] strArr = (String[])v; if (strArr.length > 0) { return strArr[0]; } else { return null; } } else if (v instanceof String) { return (String)v; } else { return v.toString(); } } }
CustomerUser.java
import lombok.Getter; import lombok.Setter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class CustomerUser extends User { private static final long serialVersionUID = -814031798199130344L; /** * 登录用户的基本信息 */ @Getter @Setter private User userDetails; public CustomerUser(String username, String password, Collection<? extends GrantedAuthority> authorities) { super(username, password, authorities); } public CustomerUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities); } public class User implements Serializable { private static final long serialVersionUID = 6253500539624699762L; public User(){} /** * 用户id */ private String userId=""; /** * 用户名,大写 */ private String userName=""; /** * 邮箱,大写 */ private String email=""; /** * 姓名 */ private String name=""; /** * 手机 */ private String phone=""; /** * 用户状态 */ private int userState; /* * 性别 0:女 1:男 */ private int sex; /** * 备注 */ private String remark; /** * 用户角色(角色码) */ private List<String> roles = new ArrayList<>(); /** * 用户权限(权限码) */ private List<String> permissions = new ArrayList<>(); /** * 有权访问的系统(系统id) */ private List<String> storeIds = new ArrayList<>(); public String getUserId() { return userId; } public void setUserId(String userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public int getUserState() { return userState; } public void setUserState(int userState) { this.userState = userState; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public List<String> getRoles() { return roles; } public void setRoles(List<String> roles) { this.roles = roles; } public List<String> getPermissions() { return permissions; } public void setPermissions(List<String> permissions) { this.permissions = permissions; } public List<String> getStoreIds() { return storeIds; } public void setStoreIds(List<String> storeIds) { this.storeIds = storeIds; } } }
UserUtils.java
import com.dimpt.common.security.CustomerUser; import com.dimpt.common.util.TokenUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.DependsOn; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; /** * @Description * @Author 胡俊敏 * @Date 2019/10/25 15:45 */ @Component @DependsOn("tokenStore") public class UserUtils { @Autowired private TokenStore tokenStore; private String getToken() { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); if(requestAttributes==null) return null; HttpServletRequest req = ((ServletRequestAttributes) requestAttributes).getRequest(); return TokenUtils.getToken(req); } /** * 获取授权服务登录的用户信息 * @return */ public UserDetails getUserDetails() { OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(getToken()); return getUserDetails(oAuth2Authentication); } /** * 获取授权服务登录的用户信息 * @param token * @return */ public UserDetails getUserDetails(OAuth2AccessToken token) { OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token); return getUserDetails(oAuth2Authentication); } /** * 获取授权服务登录的用户信息 * @param token * @return */ public UserDetails getUserDetails(String token) { OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token); return getUserDetails(oAuth2Authentication); } /** * 获取授权服务登录的用户信息 * @return */ public CustomerUser getCustomerUser() { String token = getToken(); if(StringUtils.isEmpty(token)) return null; OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token); return getCustomerUser(oAuth2Authentication); } /** * 获取授权服务登录的用户信息 * @param token * @return */ public CustomerUser getCustomerUser(OAuth2AccessToken token) { OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token); return getCustomerUser(oAuth2Authentication); } /** * 获取授权服务登录的用户信息 * @param token * @return */ public CustomerUser getCustomerUser(String token) { OAuth2Authentication oAuth2Authentication = tokenStore.readAuthentication(token); return getCustomerUser(oAuth2Authentication); } /** * 根据token获取用户名 * @param token * @return */ public String getUserName(String token) { UserDetails userDetails = getUserDetails(token); if(userDetails==null) return null; else return userDetails.getUsername(); } /** * 根据token获取用户名 * @param token * @return */ public String getUserId(String token) { CustomerUser userDetails = getCustomerUser(token); if(userDetails==null) return null; else return userDetails.getUserDetails().getUserId(); } /** * 根据token获取用户名 * @return */ public String getUserName() { UserDetails userDetails = getUserDetails(); if(userDetails==null) return null; else return userDetails.getUsername(); } /** * 根据token获取用户名 * @return */ public String getUserId() { CustomerUser userDetails = getCustomerUser(); if(userDetails==null) return null; else return userDetails.getUserDetails().getUserId(); } private UserDetails getUserDetails(OAuth2Authentication oAuth2Authentication) { if(oAuth2Authentication==null) return null; return (UserDetails) oAuth2Authentication.getPrincipal(); } private CustomerUser getCustomerUser(OAuth2Authentication oAuth2Authentication) { if(oAuth2Authentication==null) return null; return (CustomerUser) oAuth2Authentication.getPrincipal(); } }
UserServiceDetail.java
import com.dimpt.domain.entity.user.UserEntity; import com.dimpt.domain.enums.UserState; import com.dimpt.domain.mapper.service.user.UserService; import com.dimpt.common.security.CustomerUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; 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; import org.springframework.util.StringUtils; import java.util.*; /** * @Description * @Author 胡俊敏 * @Date 2019/10/24 11:09 */ @Service public class UserServiceDetail implements UserDetailsService { @Autowired private UserService userService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UserEntity user = userService.findByUserName(username); if (user == null) { throw new UsernameNotFoundException(username); } Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); //role 鉴权 List<String> roleCodes = userService.findRoleCodes(user.getUserId()); if(roleCodes!=null &&!roleCodes.isEmpty()) { for (String code : roleCodes) { //角色必须是ROLE开头 if (!code.startsWith("{ROLE}")) { code = "{ROLE}_" + code; } GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(code); grantedAuthorities.add(grantedAuthority); } } // 可用性 :true:可用 false:不可用 boolean enabled = true; // 过期性 :true:没过期 false:过期 boolean accountNonExpired = true; // 有效性 :true:凭证有效 false:凭证无效 boolean credentialsNonExpired = true; // 锁定性 :true:未锁定 false:已锁定 boolean accountNonLocked = user.getUserState()== UserState.Active; CustomerUser customerUser = new CustomerUser(user.getUserName(),user.getPassWord(),enabled,accountNonExpired,credentialsNonExpired,accountNonLocked,grantedAuthorities); //设置 SecurityUser CustomerUser.User securityUser = customerUser.new User(); securityUser.setUserId(user.getUserId()); securityUser.setUserName(user.getUserName()); securityUser.setEmail(user.getEmail()); securityUser.setName(user.getName()); securityUser.setPhone(user.getPhone()); securityUser.setSex(user.getSex()); securityUser.setUserState(user.getUserState().getValue()); //#TODO //设置用户角色 securityUser.setRoles(Collections.EMPTY_LIST); //设置用户权限 securityUser.setPermissions(Collections.EMPTY_LIST); //设置有权限访问的系统 securityUser.setStoreIds(Collections.EMPTY_LIST); customerUser.setUserDetails(securityUser); return customerUser; } }
FilterConfig.java
import com.dimpt.common.filter.OperaterFilter; 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; @Configuration public class FilterConfig { @Autowired private OperaterFilter operatorFilter; @Bean public FilterRegistrationBean registerOperatorFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(operatorFilter); registration.addUrlPatterns("/*"); registration.setName("operatorFilter"); registration.setOrder(1); //值越小,Filter越靠前。 return registration; } }
BaseOperatorAwareCommand.java
import com.dimpt.common.interfaces.IOperator; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; import java.util.Date; /** * 携带操作人信息的命令基类 */ @Getter @Setter public abstract class BaseOperatorAwareCommand implements IOperator { /** * 操作人的用户Id。本字段应根据当前登录用户取值(不应理会前端传入的数据) */ @ApiModelProperty(hidden = true) private String operatedByUserId; /** * 操作人真实姓名。本字段应根据当前登录用户取值(不应理会前端传入的数据) */ @ApiModelProperty(hidden = true) private String operatedByRealName; /** * 操作人用户名。本字段应根据当前登录用户取值(不应理会前端传入的数据) */ @ApiModelProperty(hidden = true) private String operatedByUserName; /** * 操作时间 */ @ApiModelProperty(hidden = true) private Date operatedOn; }
DeploymentByResourceCommand.java
import com.dimpt.domain.command.BaseOperatorAwareCommand; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; @Getter @Setter @ApiModel(description= "发布流程") public class DeploymentByResourceCommand extends BaseOperatorAwareCommand { @ApiModelProperty(value = "添加bpmn文件",notes = "必须是 Resource 能识别到的路径",required = true) private String bpmpResourcePath; @ApiModelProperty(value = "添加png文件",notes = "必须是 Resource 能识别到的路径") private String pngResourcePath; @ApiModelProperty(value = "流程名称",required = true) private String name; }
具体使用如下:
@RequestMapping("/deploymentByResource") @ApiOperation(value = "发布流程",notes = "项目内部资源文件部署") public JsonResult deploymentByResource(@RequestBody DeploymentByResourceCommand command) { securityUtils.logInAs(command.getOperatedByUserName()); DeploymentBuilder deploymentBuilder = repositoryService.createDeployment(); //创建Deployment对象 deploymentBuilder = deploymentBuilder.addClasspathResource(command.getBpmpResourcePath()); //添加png文件 if(!StringUtils.isEmpty(command.getPngResourcePath())) deploymentBuilder = deploymentBuilder.addClasspathResource(command.getPngResourcePath()); //部署 Deployment deployment = deploymentBuilder.name(command.getName()).deploy(); return JsonResult.success(deployment); }
command.getOperatedByUserName()
command.operatedByUserId()
command.operatedByRealName()
command.getOperatedOn()