解决springcloud实际项目中遇到的问题

问题一

在oauth2+jwt格式的鉴权授权认证token中,增加自定义字段并获取该字段

1.继承JwtAccessTokenConverter类,重写enhance方法,将userId放在jwt格式的payload中

public class UaaJwtAccessTokenConverter extends JwtAccessTokenConverter {
    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        if (accessToken instanceof DefaultOAuth2AccessToken) {
            Object principal = authentication.getPrincipal();

            if (principal instanceof  com.kunfei.uaa.service.dto.UserDTO) {
                UserDTO user = (UserDTO) principal;
                HashMap map = new HashMap<>();
                map.put("userId", user.getId());
                ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(map);
            }
        }
        return super.enhance(accessToken, authentication);
    }
}

2.在认证服务器中,增加自定义的UaaJwtAccessTokenConverter类到spring上下文

@Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new UaaJwtAccessTokenConverter();
        KeyPair keyPair = new KeyStoreKeyFactory(
             new ClassPathResource(uaaProperties.getKeyStore().getName()), uaaProperties.getKeyStore().getPassword().toCharArray())
             .getKeyPair(uaaProperties.getKeyStore().getAlias());
        converter.setKeyPair(keyPair);
        return converter;
    }

3.获取tokne并解析token中的payload,得到userId

注入JwtTokenStore

    @Autowired
    public JwtTokenStore tokenStore;

public static Optional getCurrentUserId(JwtTokenStore tokenStore) {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();
         if (authentication != null) {
             Object details = authentication.getDetails();
             if (details instanceof OAuth2AuthenticationDetails) {
                 String userId = null;
                 Object decodedDetails = ((OAuth2AuthenticationDetails) details).getDecodedDetails();
                 if (decodedDetails != null&& decodedDetails instanceof Map) {
                    userId = ((Map) decodedDetails).get("userId").toString();
                 }else {
                     String accessToken = ((OAuth2AuthenticationDetails) details).getTokenValue();
                     Map extraInfoMap = tokenStore.readAccessToken(accessToken).getAdditionalInformation();
                     userId = extraInfoMap.get("userId").toString();
                 }
                 return Optional.ofNullable(Long.valueOf(userId));
             }
         }
        return Optional.ofNullable(null);
    }

问题二:

在Restful API接口中,增加过滤器,修改response中body体的内容

1.继承HttpServletResponseWrapper(HttpServletResponse的包装实现类)

public class BodyCachingHttpServletResponseWrapper extends HttpServletResponseWrapper {

    private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    private HttpServletResponse response;
    private PrintWriter pwrite;
 
    public BodyCachingHttpServletResponseWrapper(HttpServletResponse response) {
        super(response);
        this.response = response;
    }
 
    public byte[] getBytes() {
        if(pwrite != null) {
            pwrite.close();
            return byteArrayOutputStream.toByteArray();
        }
        
        if(byteArrayOutputStream != null) {
            try {
                byteArrayOutputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return byteArrayOutputStream.toByteArray();
    }
 
    @Override
    public ServletOutputStream getOutputStream() {
        return new ServletOutputStreamWrapper(this.byteArrayOutputStream , this.response);
    }
 
    @Override
    public PrintWriter getWriter() throws IOException {
        pwrite = new PrintWriter(new OutputStreamWriter(this.byteArrayOutputStream , this.response.getCharacterEncoding()));
        return pwrite;
    }
 
    private static class ServletOutputStreamWrapper extends ServletOutputStream {
 
        private ByteArrayOutputStream outputStream;
        private HttpServletResponse response;
        
        public ServletOutputStreamWrapper(ByteArrayOutputStream outputStream, HttpServletResponse response) {
            super();
            this.outputStream = outputStream;
            this.response = response;
        }

        @Override
        public boolean isReady() {
            return true;
        }
 
        @Override
        public void setWriteListener(WriteListener listener) {
 
        }
 
        @Override
        public void write(int b) throws IOException {
            this.outputStream.write(b);
        }
 //在原有body的基础上,提交原有的内容,先是新增而不是替换,需要注释掉
//        @Override
//        public void flush() throws IOException {
//            if (! this.response.isCommitted()) {
//                byte[] body = this.outputStream.toByteArray();
//                ServletOutputStream outputStream = this.response.getOutputStream();
//                outputStream.write(body);
//                outputStream.flush();
//            }
//        }
    }
}

2.增加过滤器,替换response中body的内容

@WebFilter(filterName = "responseFilter",urlPatterns = "/*")
public class ResponseFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        BodyCachingHttpServletResponseWrapper responseWrapper = new         BodyCachingHttpServletResponseWrapper((HttpServletResponse) servletResponse);
        chain.doFilter(servletRequest, responseWrapper);
        Optional xTotalCount = Optional.ofNullable(responseWrapper.getHeader("X-Total-Count"));
        byte[] writeValueByte = null;
        if(xTotalCount.isPresent() && responseWrapper.getBytes() != null) {
            String currentTotal = xTotalCount.get();
            String currentData = new String(responseWrapper.getBytes());
            String writeValue = "{\"total\":"+currentTotal+",\"data\":"+currentData+"}";
            writeValueByte = writeValue.getBytes();
        }else {
            writeValueByte = responseWrapper.getBytes();
        }

        //重新写入输出流
        ServletOutputStream outputStream = servletResponse.getOutputStream();
        outputStream.write(writeValueByte);
        outputStream.flush();
        outputStream.close();
    }
}

3.在启动器上增加扫描servlet的注解

@ServletComponentScan

你可能感兴趣的:(解决springcloud实际项目中遇到的问题)