springmvc自定义参数解析器

先说下需求: 

前后端分离,登录后前端每次请求带有token,请求后端.希望登录过滤器解析后,能把用户的id直接在controller中获取到

实现方式:

注解形式

1.登录拦截器


public class LoginInterctor  extends HandlerInterceptorAdapter {

    private static final Logger logger = LoggerFactory.getLogger(LoginInterctor.class);

    @Resource
    private JedisSentinelPool jedisSentinelPool;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod))
            return true;
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //从header中得到token
        AuthorizationToken token = getToken(request);
        Jedis jedis = jedisSentinelPool.getResource();
        String tokenString = jedis.get(token.getUserId().toString());
        if (tokenString.equals(token.getToken())) {
            request.setAttribute("loginId", token.getUserId());
            return true;
        }else{
            throw new TalentChainException(ResultCodeEnum.NOT_LOGIN.getCode(), ResultCodeEnum.NOT_LOGIN.getMessage());
        }
    }



    public AuthorizationToken getToken(HttpServletRequest request){
        String value = request.getHeader(RequestConstant.AUTHORIZATION);
        if (StringUtils.isBlank(value))
            value = request.getParameter(RequestConstant.AUTHORIZATION);
        if (StringUtils.isBlank(value)) {
            value = Optional.ofNullable(request.getAttribute(RequestConstant.AUTHORIZATION))
                    .map(o -> String.valueOf(o))
                    .orElse("");
        }
        AuthorizationToken token = new AuthorizationToken(value);
        return token;
    }
}

AuthorizationToken会将传入的token解析.与redis中对比后获取当前登录用户的id.

登录过滤器配置

在springmvc.xml中加入.mapping代表过滤所有.exclude-mapping代表除此之外.,下面是说带有special的请求之外请求都将被拦截;


    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/**/special/**"/>
            <bean class="com.chain.talent.util.aop.interceptor.LoginInterctor"/>
        </mvc:interceptor>
    </mvc:interceptors>

2.自定义参数解析器

a.注解

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUserId {


}

b.解析器


public class CurrentUserIdResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        if (methodParameter.getParameterType().isAssignableFrom(Long.class) &&
                methodParameter.hasParameterAnnotation(CurrentUserId.class)) {
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        return (Long)nativeWebRequest.getAttribute("loginId", RequestAttributes.SCOPE_REQUEST);
    }
}

代码比较简单.只是将request中的loginId去除.放入使用@CurrentUserId中

c.解析器配置

    <!-- mvc注解驱动 -->
    <mvc:annotation-driven>
        <mvc:argument-resolvers>
            <bean class="com.chain.talent.util.aop.interceptor.CurrentUserIdResolver"/>
        </mvc:argument-resolvers>
    </mvc:annotation-driven>

3.controller中使用

 @RequestMapping(value = "/userCenter" ,method = RequestMethod.GET)
    JsonResult MineInfo(@CurrentUserId Long userId){
        return JsonResult.SUCCESS().putResult("user",userService.getJobHunterInfoByUserId(userId));
    }

代码不多.

但是最初我是想在登录的过滤器中修改request中的请求参数.将userId放入请求参数中.失败后查了一些文章说: 为了安全,不建议修改请求参数.由于水平有限我不会改源码.于是,我想在controller中的方法接受前多放一些参数,发现了一个有趣的注解:

@modelattribute..有兴趣的可以看一下这个注解.我认为它对于我现在的业务并不是很符合.然后在github上发现了一个项目.我认为很不错的解决了我的问题.

如果上述代码比较杂乱.没有看懂.可以直接到github上看别人的源码;

https://github.com/ScienJus/spring-restful-authorization

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值