11111111111
知识共享平台
知识共享平台

讨教大学平台

  • 首页
  • 免费课
  • 精品课
  • 讨教题库
  • 企业服务

    hot

  • 下载APP
  • 证书查询
  • 关于我们
我问
讨教号
搜索
消息
  • 我的文章

    我的关注

    我的问答

    我的秘密

    我的评论

    我的订阅

    我的打赏

    我的钱包

    我的通知

    我的设置

    退出登录

  • ×

    登录

    讨教 | 通行证

    登录
    立即注册
    忘记密码?
    使用微信登录

    提问 ×

    写下你的问题,准确的表述更容易得到答案

    类型话题

    选择支付方式
    您的讨教币 111 付费金额

    Token认证,如何快速方便获取用户信息 尹吉欢 JAVA葵花宝典 今天

    JAVA葵花宝典
    2019-06-28 17:28:58
    16篇 作品
    2227 总阅读量

    背景

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

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

    方式一(很挫)

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

    1. @GetMapping("/hello")

    2. public String test(HttpServletRequest request) {

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

    4. JWTResult result = JWTUtils.checkToken(token);

    5. Long userId = result.getUserId();

    6. }

    方式二(优雅)

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

    1. @Override

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

    3. throws IOException, ServletException {

    4. HttpServletRequest httpRequest = (HttpServletRequest) request;

    5. HttpServletResponse httpResponse = (HttpServletResponse) response;

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

    7. JWTResult result = JWTUtils.checkToken(token);

    8. Long userId = result.getUserId();

    9. HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) {

    10. @Override

    11. public String getHeader(String name) {

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

    13. return userId .toString();

    14. }

    15. return super.getHeader(name);

    16. }

    17. };

    18. chain.doFilter(requestWrapper, httpResponse);

    19. }

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

    1. @GetMapping("/hello")

    2. public String save2(HttpServletRequest request) {

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

    4. }

    方式三(很优雅)

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

    GET参数方式

    在Filter中追加参数:

    1. @Override

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

    3. throws IOException, ServletException {

    4. HttpServletRequest httpRequest = (HttpServletRequest) request;

    5. HttpServletResponse httpResponse = (HttpServletResponse) response;

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

    7. JWTResult result = JWTUtils.checkToken(token);

    8. Long userId = result.getUserId();

    9. HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) {

    10. @Override

    11. public String[] getParameterValues(String name) {

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

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

    14. }

    15. return super.getParameterValues(name);

    16. }

    17. @Override

    18. public Enumeration getParameterNames() {

    19. Set paramNames = new LinkedHashSet<>();

    20. paramNames.add("loginUserId");

    21. Enumeration names = super.getParameterNames();

    22. while(names.hasMoreElements()) {

    23. paramNames.add(names.nextElement());

    24. }

    25. return Collections.enumeration(paramNames);

    26. }

    27. };

    28. chain.doFilter(requestWrapper, httpResponse);

    29. }

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

    1. @GetMapping("/hello")

    2. public String save2(String name, Long loginUserId) {

    3. // loginUserId 就是Filter中追加的值

    4. }

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

    1. @PostMapping("/hello")

    2. public String save2(User user, Long loginUserId) {


    3. }

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

    先创建一个参数实体类:

    1. public class User {


    2. private String name;


    3. private Long loginUserId;

    4. }

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

    1. @PostMapping("/hello")

    2. public User save2(User user) {

    3. return user;

    4. }

    用PostMan测试一下,表单方式是直接支持的:再次试下Json提交方式:

    1. @PostMapping("/hello")

    2. public User save2(@RequestBody User user) {

    3. return user;

    4. }

    看下图,失败了,得重新想办法实现下只需要在HttpServletRequestWrapper中重新对提交的内容进行修改即可:

    1. @Override

    2. public ServletInputStream getInputStream() throws IOException {

    3. byte[] requestBody = new byte[0];

    4. try {

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

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

    7. map.put("loginUserId", loginUserId);

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

    9. } catch (IOException e) {

    10. throw new RuntimeException(e);

    11. }

    12. final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);

    13. return new ServletInputStream() {

    14. @Override

    15. public int read() throws IOException {

    16. return bais.read();

    17. }


    18. @Override

    19. public boolean isFinished() {

    20. return false;

    21. }


    22. @Override

    23. public boolean isReady() {

    24. return true;

    25. }


    26. @Override

    27. public void setReadListener(ReadListener listener) {


    28. }

    29. };

    30. }

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

    本网站内容仅代表作者本人的观点,不代表本网站的观点和看法,与本网站立场无关,如有侵权请联系讨教。
    给作者打赏,鼓励TA抓紧创作
    0人打赏金额
    JAVA葵花宝典
    16篇 作品
    2227 总阅读量
    评论
    您可能感兴趣的文章

    项目管理服务模式

    敏捷项目管理与传统项目管理比较

    项目管理的特点

    PMO是什么?是管项目经理的嘛?

    项目经理必须关注的开会十大关键问题!

    项目的组成要素

    热门话题 更多话题
    精益生产 质量管理 智能制造
    职场效率 项目管理 讨教
    AI 大数据 六西格玛
    ×

    给作者打赏,鼓励TA抓紧创作!

    选择支付方式
    选择打赏金额
    注:打赏的收益归作者,非平台

    微信扫描支付

    打赏金额: 1元

    ×

    给作者打赏,鼓励TA抓紧创作!

    您的讨教币
    填写您打赏讨教币数量
    输入密码

    111

    注:打赏的收益归作者,非平台

    微信扫描支付

    打赏金额: 1元