精华内容
下载资源
问答
  • 权限控制,访问API的请求必须要带上事先认证后获取的Token才可以。认证的话就在Filter中进行的,会获取请求的Token进行验证,如果成功了可以得到Token中的用户信息,本文的核心就是讲解如何将用户信息(用户ID)...

    背景

    我们有一个Web项目,这个项目提供了很多的Rest API。也做了权限控制,访问API的请求必须要带上事先认证后获取的Token才可以。

    认证的话就在Filter中进行的,会获取请求的Token进行验证,如果成功了可以得到Token中的用户信息,本文的核心就是讲解如何将用户信息(用户ID)优雅的传递给API接口(Controller)。

    方式一(很挫)

    我们在Filter中进行了统一拦截,在Controller中获取用户ID的话,仍然可以再次解析一遍Token获取用户ID

    @GetMapping("/hello")

    public String test(HttpServletRequest request) {

    String token = request.getHeader("token");

    JWTResult result = JWTUtils.checkToken(token);

    Long userId = result.getUserId();

    }

    方式二(优雅)

    方式一需要重新解析一遍Token, 浪费资源。我们可以直接将Filter中解析好了的用户ID直接通过Header传递给接口啊。

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

    throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) request;

    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String token = request.getHeader("token");

    JWTResult result = JWTUtils.checkToken(token);

    Long userId = result.getUserId();

    HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) {

    @Override

    public String getHeader(String name) {

    if (name.equals("loginUserId")) {

    return userId .toString();

    }

    return super.getHeader(name);

    }

    };

    chain.doFilter(requestWrapper, httpResponse);

    }

    接口中直接从Header中获取解析好了的用户ID:

    @GetMapping("/hello")

    public String save2(HttpServletRequest request) {

    Long userId = Long.parseLong(request.getHeader("loginUserId"));

    }

    方式三(很优雅)

    通过Header传递确实很方便,但如果你有代码洁癖的话总会觉得怪怪的,能不能不用Header方式,比如说我就在方法上定义一个loginUserId的参数,你给我直接注入进来,这个有点意思哈,下面我们来实现下:

    GET参数方式

    在Filter中追加参数:

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

    throws IOException, ServletException {

    HttpServletRequest httpRequest = (HttpServletRequest) request;

    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String token = request.getHeader("token");

    JWTResult result = JWTUtils.checkToken(token);

    Long userId = result.getUserId();

    HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) {

    @Override

    public String[] getParameterValues(String name) {

    if (name.equals("loginUserId")) {

    return new String[] { userId .toString() };

    }

    return super.getParameterValues(name);

    }

    @Override

    public Enumeration<String> getParameterNames() {

    Set<String> paramNames = new LinkedHashSet<>();

    paramNames.add("loginUserId");

    Enumeration<String> names = super.getParameterNames();

    while(names.hasMoreElements()) {

    paramNames.add(names.nextElement());

    }

    return Collections.enumeration(paramNames);

    }

    };

    chain.doFilter(requestWrapper, httpResponse);

    }

    接口中直接填写参数即可获取:

    @GetMapping("/hello")

    public String save2(String name, Long loginUserId) {

    // loginUserId 就是Filter中追加的值

    }

    对于post请求,也可以用这种方式:

    @PostMapping("/hello")

    public String save2(User user, Long loginUserId) {

    }

    可是往往我们在用post请求的时候,要么就是表单提交,要么就是json体的方式提交,一般不会使用get方式参数,这也就意味着这个loginUserId我们需要注入到对象中:

    先创建一个参数实体类:

    public class User {

    private String name;

    private Long loginUserId;

    }

    先模拟表单提交的方式,看看行不行:

    @PostMapping("/hello")

    public User save2(User user) {

    return user;

    }

    用PostMan测试一下,表单方式是直接支持的:

    8114427cc874f53c69695c3ef7f3405c.png

    再次试下Json提交方式:

    @PostMapping("/hello")

    public User save2(@RequestBody User user) {

    return user;

    }

    看下图,失败了,得重新想办法实现下

    fff6919e1771d3be986a14be82f244ee.png

    只需要在HttpServletRequestWrapper中重新对提交的内容进行修改即可:

    @Override

    public ServletInputStream getInputStream() throws IOException {

    byte[] requestBody = new byte[0];

    try {

    requestBody = StreamUtils.copyToByteArray(request.getInputStream());

    Map map = JsonUtils.toBean(Map.class, new String(requestBody));

    map.put("loginUserId", loginUserId);

    requestBody = JsonUtils.toJson(map).getBytes();

    } catch (IOException e) {

    throw new RuntimeException(e);

    }

    final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);

    return new ServletInputStream() {

    @Override

    public int read() throws IOException {

    return bais.read();

    }

    @Override

    public boolean isFinished() {

    return false;

    }

    @Override

    public boolean isReady() {

    return true;

    }

    @Override

    public void setReadListener(ReadListener listener) {

    }

    };

    }

    到此为止,我们就可以直接将Token解析的用户ID直接注入到参数中了,不用去Header中获取,是不是很方便。

    欢迎加入我的知识星球,一起交流技术,免费学习猿天地的课程(http://cxytiandi.com/course)

    PS:目前星球中正在星主的带领下组队学习Spring Cloud,等你哦!

    47cca70a0a6df4631d529a38b0c88482.png

    展开全文
  • ABAP面试大全

    2013-12-30 15:44:36
    7.3 smartform 中如何控制段落、单个字符输出格式? 19 8. RFC和 BAPI 20 8.1 RFC 20 8.1.1什么是RFC,有哪些通信模式? 20 8.1.2 RFC中涉及到常用的事务代码有哪些? 20 8.1.3根据调用方式的不同,RFC接口提供了...
  • asp.net知识库

    2015-06-18 08:45:45
    Coalesys PanelBar + R.a.d Treeview +Xml 构建的Asp.net 菜单和权限管理模块 突破屏蔽限制,自己的网站使劲弹新IE窗口 对页面SCROLLING的CSS不能生效原因 .Net 中IE使用WinForm控件的使用心得。 动态加载用户控件的...
  • [Oracle.11g权威指南(第2版)].谷长勇.扫描版.pdf

    千次下载 热门讨论 2013-06-23 21:16:09
    本章将介绍Oracle系统中的用户管理、权限控制、角色、资源及数据库的审计等方面的内容。 15.1 创建与管理用户账户 343 15.1.1 配置身份验证 343 15.1.2 创建用户的语法 343 15.1.3 创建用户实例 344 15.1.4 修改用户...

空空如也

空空如也

1 2 3 4
收藏数 61
精华内容 24
关键字:

导出接口如何做权限控制