基于springboot 2.0+jwt登录验证

基于springboot 2.0+jwt的登录验证


一、准备环境,jdk8.0+springboot 2.0+jwt 3.4.0+IDEA
二、jwt 的meavn 依赖

		<dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

三、配置WebMvcConfigurer,springboot 2.0之前用的是WebMvcConfigurerAdapter(现在已废弃了)

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

	//注入登录拦截器
    @Autowired
    LoginInterceptor login;
    
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    	//这得的login用两种方式,一种像本文一样用注入的方式,第二种是用new LoginInterceptor ();但是这用new 的方式的话,在LoginInterceptor 种注入service层会不起作用。所以用注入的方式。
        registry.addInterceptor(login)
        		//添加需要拦截的地址,静态文件也可以再这里做配置,用excludePathPatterns是不拦截
                .addPathPatterns("/api/admin/**");
    }
    
}

四、自定两个注解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
    boolean required() default true;
}

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
    boolean required() default true;
}

五、配置登录拦截器

@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {

        String token = request.getHeader("token");// 从 http 请求头中取出 token
        // 如果不是映射到方法直接通过
        if(!(object instanceof HandlerMethod)){
            return true;
        }
        HandlerMethod handlerMethod=(HandlerMethod)object;
        Method method=handlerMethod.getMethod();

        //检查是否有passtoken注释,有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //检查有没有需要用户权限的注解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // 执行认证
                if (token == null) {
                    throw new RuntimeException("无token,请重新登录");
                }
                // 获取 token 中的 user id
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("401");
                }
                log.info("userId:{}",userId);
                UserPojo user = userService.findUserById(userId);
                if ( null == user) {
                    throw new RuntimeException("用户不存在,请重新登录");
                }
                // 验证 token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getUserPwd())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new RuntimeException("401");
                }
                return true;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

六、增加token获取方式

@Override
    public String getToken(UserPojo user) {
        String token="";
        token= JWT.create().withAudience(user.getUserId().toString())
                .sign(Algorithm.HMAC256(user.getUserPwd()));
        return token;
    }

七、登录代码

@RestController
@RequestMapping("/api/admin/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private TokenService tokenService;

    @UserLoginToken
    @ApiOperation(value = "第一个接口")
    @RequestMapping(value ="test",method = RequestMethod.GET)
    public BaseResponse first(){
        return new BaseResponse(200,"成功","Hello world");
    }


    @ApiOperation(value = "后台登录接口")
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    public BaseResponse login(String userName, String userPwd ){
        UserPojo user = userService.getUserByUserNameAndUserPwd(userName, userPwd);
        if (null != user){
            String accessToken = tokenService.getToken(user);
            Map<String,Object> map = new HashMap<>();
            map.put("token",accessToken);
            return new BaseResponse(200,"登录成功",map);
        }else {
            return new BaseResponse(500,"登录失败,密码或账号错误!",null);
        }
    }
}

之前自定义的连个注解就是,在需要做登录验证的方法上加入@UserLoginToken就是需要验证,@PassToken就是不需要验证,不写默认是需要验证的。
八、总结
这里的UserPojo就是一个简单的 用户名和密码,数据库也是对应的。
测试的时候直接放问login这个地址,输入用户名和密码;就回返回一个token,可以直接返回代码里的那个map。我这里是写了一个统一的相应类。
测试访问test的时候,把登录返回的token写在header里,就可以显示访问正常,如果不带的话就回返回没有token,在LoginInterceptor里,这里验证了token的有效性,以及token种所携带的用户的有效性。这里的jwt只是做了一个简单的生成方式,感兴趣的可以去单独看看jwt,jwt是可以加盐的,以及token有效期,这些都是可以设置的,然后在登录拦截器里做对应的处理就行。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值