java 通过 token + filter 自动设置操作人信息

由于项目使用 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()

 

posted @ 2020-04-26 11:41  hujunmin  阅读(824)  评论(0编辑  收藏  举报