文档章节

如何实现小程序使用自定义注解获取当前登录用户???

code-ortaerc
 code-ortaerc
发布于 11/19 23:51
字数 1312
阅读 68
收藏 0

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

业务场景

  • 在我们的程序代码中很多接口的调用都会有限制,需要在用登录的状态下才能进行操作,本篇内容主要使用定义注解在调用接口时候进行登录验证拦截。

自定义注解

/**
 * 在Controller的方法参数上使用这个注解,该方法在映射是会注入当前登录对象
 *
 * @Author 林必昭
 * @Date 2019/11/12 17:29
 */

@Target({ElementType.PARAMETER, ElementType.METHOD})    //即可以修饰参数,也可以修饰方法
@Retention(RetentionPolicy.RUNTIME)                     //运行时生效
public @interface LoginUser {
}

自定义一个处理程序方法参数解析器(类)并实现HandlerMethodArgumentResolver

/**
 * 一般在controller方法中都要获取当前登录用户,我们可以自定义HandlerMethodArgumentResolver(处理程序方法参数解析器)
 * 来获取当前登录用户,有@LoginUser注解的方法参数,表示注入当前登录用户
 *
 * @Author 林必昭
 * @Date 2019/11/12 18:56
 */
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String LOGIN_TOKEN_KEY = "X-HomeShop-Login-Token";

    /**
     * 用于判断判断Controller层中的参数,是否满足条件,满足条件则执行resolveArgument方法,不满足则跳过
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        //判断参数类型是否是Integer类型,和是否有注解@LoginUser注解修饰
        return parameter.getParameterType().isAssignableFrom(Integer.class) && parameter.hasParameterAnnotation(LoginUser.class);
    }

    /**
     * 在supportsParameter方法返回true的情况下才会被调用。用于处理一些业务,返回Object就是controller
     * 方法上的形参对象,也就是将返回值赋值给Controller的参数
     */
    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer container,
                                  NativeWebRequest request,
                                  WebDataBinderFactory factory) throws Exception {
        //从请求头中获取参数信息
        String token = request.getHeader(LOGIN_TOKEN_KEY);
        if (token == null || token.isEmpty()){
            return null;
        }
        //其实UserTokenManager.getUserId(token)返回的就是userId
        return UserTokenManager.getUserId(token);
    }
}

UserTokenManager

实际上UserTokenManager.getUserId(token),最后返回的就是我们的userId,而resolveArgement方法就是将最后的返回结果,赋值给我们Controller的参数 userId

/**
 * 用户token维护类
 *
 * @Author 林必昭
 * @Date 2019/11/11 19:51
 */
public class UserTokenManager {

    public static String generateToken(Integer id) {
        JwtHelper jwtHelper = new JwtHelper();
        return jwtHelper.createToken(id);
    }
    public static Integer getUserId(String token) {
        JwtHelper jwtHelper = new JwtHelper();
        Integer userId = jwtHelper.verifyTokenAndGetUserId(token);
        if(userId == null || userId == 0){
            return null;
        }
        return userId;
    }
}

自定义配置类把上述的Resolver交给Spring容器处理

/**
 * @Author 林必昭
 * @Date 2019/11/12 19:09
 */
@Configuration
public class WxWebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new LoginUserHandlerMethodArgumentResolver());
    }
}

Controller使用

当接口调用需要登录用户身份时候,需要验证当前用是否处于登录状态,比如:获取用户信息,必须是在登录状态下才能获取,这样就可以使用@LoginUser注解验证了:

/**
 * 登录授权API
 *
 * @Author 林必昭
 * @Date 2019/9/22 10:19
 */
@Api(tags = "登陆授权API")
@Slf4j
@RestController
@RequestMapping("/api/auth")
public class ApiAuthController extends ApiBaseController {
     /**
     * 获取用户信息
     */
    @GetMapping("/info")
    @ApiOperation(value = "获取用户信息接口")
    public Object getUserInfo(@LoginUser Integer userId){
        if (userId==null){
            return ServerResponse.createByErrorCodeMessage(ResponseCodeEnum.NEED_LOGIN.getCode(),"请先登录");
        }
        User user = userRepository.findUserByUserId(userId);
        Map<Object,Object> userData = new HashMap<>();
        userData.put("nickName", user.getNickname());
        userData.put("avatar", user.getAvatar());
        userData.put("gender", user.getGender());
        userData.put("mobile", user.getMobile());

        return ServerResponse.createBySuccess(userData);
    }

}

使用Session保存当前用户信息

我觉得自定义登录验证注解@LoginUser这个验证机制跟我们web领域session管理用户登录信息差不多,用户登录之后将用户信息保存到我们的session中,在接口调用的时候需要验证用户是否存在与session中,如果不存在,就需要强制将用登录,接下来看代码:

UserController

/**
 * @Author 林必昭
 * @Date 2019/6/16 16:34
 */

@Slf4j
@Controller
@RequestMapping("/user/")
public class UserController {

    @Autowired
    UserService userService;

    /**
     * 用户登录,将信息保存在session中
     *
     * @param username
     * @param password
     * @param session
     * @return
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse<User> login(String username, String password, HttpSession session) {
        ServerResponse<User> response = userService.login(username, password);
        if (response.isSuccess()) {
            session.setAttribute(Constant.CURRENT_USER, response.getData());
        }
        return response;
    }

    /**
     * 获取用户信息
     *
     * @param session
     * @return
     */
    @RequestMapping(value = "get_information", method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse<User> get_information(HttpSession session) {
        User user = (User) session.getAttribute(Constant.CURRENT_USER);
        if (user == null) {
            return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), "用户未登陆,需要强制登陆 status=10");
        }
        return userService.getInformation(user.getId());
    }

}

用户登录之后,我们将用户信息通过session.setAttribute()保存到session中,在我们获取用户信息接口的时候,我们要在session中获取当前的登录用户信息,如果session不存在该用户信息,就引导用户去登录,否则执行下来的操作!

总结

个人觉得小程序自定义注解获取当前登录用户与session管理当前登录用户机制原理差不太多,只是换了一种方式来实现罢了,实现自定义注解来获取当前登录用户主要步骤是:自定义登录注解@LoginUser,接着自定义一个处理程序方法参数解析器(类)并实现HandlerMethodArgumentResolver,覆盖接口的两个方法,最后将我们自定义的参数解析器配置到Spring容器,然后我们就可以在Controller层使用了,对应HandlerMethodArgumentResolver的两个方法的作用,我在注释上已经解释清楚了,不清楚的可以看看他的源码来加深理解。

© 著作权归作者所有

code-ortaerc
粉丝 0
博文 32
码字总数 40905
作品 0
广州
程序员
私信 提问
基于注解的用户权限拦截Spring HandlerInterceptor

Spring Boot (v2.0.5.RELEASE) 程序中有些资源(接口)是需要用户登录才能够使用的,或者是具有某种角色的用户(比如普通登录用户,或者系统管理员等)才能使用,本篇文章先为大家讲解如何控...

FutaoSmile丶
2018/09/23
0
0
通过 HttpAuthenticationMechanism 执行 Web 身份验证

通过 Java EE 8 中新的注解驱动的 HTTP 身份验证机制执行经典和自定义的 Servlet 身份验证 系列内容: 此内容是该系列 4 部分中的第 # 部分: Java EE 8 Security API 入门,第 2 部分 http...

Alex Theedom
2018/04/02
0
0
Spring Security教程

Spring Security是一个灵活和强大的身份验证和访问控制框架,以确保基于Spring的Java Web应用程序的安全。 在这些简单Spring Security4 一系列教程中的 Spring Security 示例是基于新的Sprin...

易百教程
2016/08/30
666
1
SpringBoot集成SpringSecurity(入门级)

Springboot集成SpringSecurity 目录创建于2017-12-18 Springboot集成SpringSecurity Demo 快速上手-初步入门: 创建单用户单角色的安全控制 添加依赖...

mmythos
2017/12/30
0
0
(转自:孤傲苍狼)简单模拟Sping MVC

转自: http://www.cnblogs.com/xdp-gacl/p/4101727.html 在Spring MVC中,将一个普通的java类标注上Controller注解之后,再将类中的方法使用RequestMapping注解标注,那么这个普通的java类就...

独钓渔
2016/03/14
769
0

没有更多内容

加载失败,请刷新页面

加载更多

采购单品汇总_华南.xlsx

import pandas as pdimport matplotlib.pyplot as pltimport matplotlib as mp1mp1.rcParams["font.family"] = "STFangsong"# 加载《销售》表数据df1 = pd.read_excel(r"C:\Us......

龙玉滕
今天
5
0
OSChina 周五乱弹 —— 一次四千 要4次还能多给一千

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @这次装个文艺青年吧 :#今日歌曲推荐# 分享金志文的单曲《远走高飞》: 版权又回来了现在听歌得好几个软件 《远走高飞》- 金志文 手机党少年们...

小小编辑
今天
7
0
Spring Cloud Alibaba 实战(十) - Spring Cloud GateWay

> 本文主要内容是:为什么要使用网关,整合Gateway,Gateway核心学习:Route,Predicate,Filter,最后使用Gateway聚合微服务请求 先总结至此的架构 1 网关的价值 不使用网关行嘛? 各个请求直接打在...

JavaEdge
今天
4
0
【CKB.DEV 茶话会】第二期:聊聊 CKB 钱包和 Nervos DAO 全流程

CKB.DEV 茶话会第二期:聊聊 CKB 钱包和 Nervos DAO 全流程 为了鼓励更多优秀的开发者和研究人员参与到 CKB 的开发和生态建设中去,我们希望组织一系列 CKB Developer Seminar(CKB.DEV 茶话...

NervosCommunity
今天
4
0
聊聊rocketmq的HAClient

序 本文主要研究一下rocketmq的HAClient HAClient rocketmq-all-4.6.0-source-release/store/src/main/java/org/apache/rocketmq/store/ha/HAService.java class HAClient extends Serv......

go4it
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部