由于项目使用 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: 复制输入流
*
* @param inputStream
* @return
*/
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 roles = new ArrayList<>();
/**
* 用户权限(权限码)
*/
private List permissions = new ArrayList<>();
/**
* 有权访问的系统(系统id)
*/
private List 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 getRoles() {
return roles;
}
public void setRoles(List roles) {
this.roles = roles;
}
public List getPermissions() {
return permissions;
}
public void setPermissions(List permissions) {
this.permissions = permissions;
}
public List getStoreIds() {
return storeIds;
}
public void setStoreIds(List 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 grantedAuthorities = new HashSet<>();
//role 鉴权
List 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()