• SpringBoot集成JWT实现token验证


    本文抄袭自 https://www.jianshu.com/p/e88d3f8151db

    本文在 使用IDEA快速搭建基于Maven的SpringBoot项目(集成使用Redis) 基础上继续

    引入JWT依赖

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

    自定义两个注解

    @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;
    }

    登录用户类

    public class LoginUser implements Serializable {
        String id;
        String username;
        String password;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }

    拦截器

    package com.blaze.demo.interceptor;
    
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.exceptions.JWTDecodeException;
    import com.auth0.jwt.exceptions.JWTVerificationException;
    
    import com.blaze.demo.annotation.PassToken;
    import com.blaze.demo.annotation.UserLoginToken;
    import com.blaze.demo.model.LoginUser;
    import com.blaze.demo.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.method.HandlerMethod;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.lang.reflect.Method;
    
    
    
    public class AuthenticationInterceptor implements HandlerInterceptor {
        @Autowired
        UserService userService;
        @Override
        public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
            String token = httpServletRequest.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");
                    }
                    LoginUser user = userService.findUserById(userId);
                    if (user == null) {
                        throw new RuntimeException("用户不存在,请重新登录");
                    }
                    // 验证 token
                    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
                    try {
                        jwtVerifier.verify(token);
                    } catch (JWTVerificationException e) {
                        throw new RuntimeException("401");
                    }
                    return true;
                }
            }
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    
        }
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
    
        }
    }

    配置拦截器

    package com.blaze.demo.config;
    
    
    import com.blaze.demo.interceptor.AuthenticationInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    
    @Configuration
    public class InterceptorConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(authenticationInterceptor())
                    .addPathPatterns("/**");    // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录
        }
    
        @Bean
        public AuthenticationInterceptor authenticationInterceptor() {
            return new AuthenticationInterceptor();
        }
    }

    接口Controller

        @GetMapping("/test01")
        public String test01() {
            return "不需要token";
        }
    
        @UserLoginToken
        @GetMapping("/test02")
        public String test02() {
            return "需要token";
        }
    
        @ResponseBody
        @PostMapping("/login")
        public Object login(@ApiParam(value = "账号") @RequestParam String account,
                            @ApiParam(value = "密码") @RequestParam String password) {
            JSONObject jsonObject = new JSONObject();
            LoginUser userForBase = userService.queryAdminByAccount(account);
            if (userForBase == null) {
                jsonObject.put("message", "登录失败,用户不存在");
                return jsonObject;
            } else {
                if (!userForBase.getPassword().equals(password)) {
                    jsonObject.put("message", "登录失败,密码错误");
                    return jsonObject;
                } else {
                    String token = getToken(userForBase);
                    jsonObject.put("token", token);
                    jsonObject.put("user", userForBase);
                    return jsonObject;
                }
            }
        }
    
        public static String getToken(LoginUser user) {
            String token = "";
            token = JWT.create().withAudience(user.getId())
                    .sign(Algorithm.HMAC256(user.getPassword()));
            return token;
        }
  • 相关阅读:
    查询表中列转换为json
    查看死锁
    利用vba将excel中的图片链接直接转换为图片
    npoi与memcached中的ICSharpCode.SharpZipLib版本冲突的解决方案
    网页爬虫的一些笔记
    从远程服务器数据库中同步数据到本地数据库 sql server 2008 开启分布
    配置ST3在浏览器中打开
    在 sublime text 3 中添加 Emmet (ZenCoding)
    win2008远程桌面会话数增加
    20150728月度会议
  • 原文地址:https://www.cnblogs.com/blazeZzz/p/11364792.html
Copyright © 2020-2023  润新知