一文学会JWT登录验证操作。

首先是基于springboot,来操作的简单的创建项目跳过直接上正文

1.创建一个项目

我们先创建一个项目,

实现实体类,dao,service,controller

先实现登录业务,

@PostMapping("login.do")
public String login(String username, String password){return "登录"}

导入依赖实现swagger

<!--导入swagger -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
    <exclusions>
        <exclusion>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.swagger</groupId>
    <artifactId>swagger-models</artifactId>
    <version>1.5.21</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>1.9.6</version>
</dependency>
​

配置文件

@Configuration
//激活swagger配置
@EnableSwagger2
public class SwaggerConfig {
    //创建RestApi文档生成
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
//指定扫描包的路径(必须)
                .apis(RequestHandlerSelectors.basePackage("xxx.controller"))//com.java2205.logindemo.controller扫描到controller
                .paths(PathSelectors.any())
                .build();
    }
    //api相关的信息说明
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2构建RESTful API")
                .description("rest api 文档构建利器")
                .version("1.0")
                .build();
    }
}

创建返回的Vo

package com.java2205.logindemo.vo;
​
import lombok.Getter;
import lombok.Setter;
​
/**
​
 */
@Setter
@Getter
public class ResultVo {
    public static final int SUCCESS = 20000;
    public static final int FAIL = 40000;
    int code;
    String message;
    Object data;
​
    public static ResultVo success(String message,Object data){
        ResultVo rd = new ResultVo();
        rd.setData(data);
        rd.setMessage(message);
        rd.setCode(SUCCESS);
        return rd;
    }
​
    public static ResultVo fail(String message,Object data){
        ResultVo rd = new ResultVo();
        rd.setCode(FAIL);
        rd.setData(data);
        rd.setMessage(message);
        return rd;
    }
}

更新登录

@PostMapping("login.do")
public ResultVo login(String username, String password){
    TUser loginUser = userService.login(username,password);
   
​
    return ResultVo.success("登录成功", "");
}

当我们登录成功以后要利用token拿去用户,所有要用JWT来实现

2.登录需要产生token来验证,

引入JWT来实现。

先导入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

导入两个依赖来实现JWT的功能

创建一个JWTutli

public class JWTUtil {
    //定义密钥
    public static final String SECRET = "XASDAS";
    //定义token的有效时间
    public static final int EXPIRED  = 10*1000;
    //最大过期时间
    public static final long EXPIREDMAX  = 40*1000;
    public static final String ACCOUNT ="account";
​
    //创建toke,暂时弃用
    public static String createToken(String account){
        try {
            //根据密码创建算法,secret是密钥,可以自定义
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            //创建token,Issuer是token的拥有人,可以自定义
            String token = JWT.create()
                    .withClaim(ACCOUNT,account)
                    .withExpiresAt(new Date(System.currentTimeMillis()+EXPIRED))
                    .sign(algorithm);
            return token;
        } catch (JWTCreationException exception){
            exception.printStackTrace();
            throw exception;
        }
    }
    
    
    
    //判断是token
    public static boolean createTokens(String token){
        return  createTokens.containsKey(token);
    }
    //创建map缓存
    public static Map<String,Object> createTokens=new HashMap<>();
    //保持token和时间到map缓存中
    public static void saveToken(String token,long time){
        createTokens.put(token, time);
    }
    //更具token获取map缓存中的时间
    public static Object getToken(String token){
         return createTokens.get(token);
    }
    //获取当前时间
    public static long currentTime(){
        return System.currentTimeMillis();
    }
    //移除map缓存中的token
    public static void remove(String token){
        createTokens.remove(token);
    }
    
    
    //创建token实际运用版本
    public static String createToken(String account,long currentTime){//传入账号和创建时间
        try {
            //根据密码创建算法,secret是密钥,可以自定义
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            //创建token,Issuer是token的拥有人,可以自定义
            String token = JWT.create()
                    .withClaim(ACCOUNT,account)
                    .withExpiresAt(new Date(currentTime+EXPIRED))//token的有效期,
                    .sign(algorithm);
            return token;
        } catch (JWTCreationException exception){
            exception.printStackTrace();
            throw exception;
        }
    }
​
    //验证token
    public static boolean verify(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                    .build(); //Reusable verifier instance
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (JWTVerificationException exception){
            //Invalid signature/claims
            exception.printStackTrace();
            throw exception;
        }
      //  return false;
    }
//解析
    public static String getAccount(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            //获取自定义参数
            String account =  jwt.getClaim(ACCOUNT).asString();
            return account;
        } catch (JWTDecodeException exception){
            //Invalid token
            exception.printStackTrace();
            throw exception;
        }
    }
}

然后跟新登录

@RestController
public class LoginController {
    @Autowired
    TUserServiceImpl userService;
    @PostMapping("login.do")
    public ResultVo login(String username, String password){
        TUser loginUser = userService.login(username,password);
        //生成token并且返回
        
        //生成token并且返回
        long times=JWTUtil.currentTime();
        String token =  JWTUtil.createToken(loginUser.getUname(),times);
        JWTUtil.saveToken(token,times);
        //用来在swagger中能看见map中的token,
       Map<String,Object> map = new HashMap<>();
        map.put("token",token);
​
        return ResultVo.success("登录成功", map);
    }
}

创建一个新的操作

@RestController
@RequestMapping("tUser")
public class TUserController {
    @Autowired
    TUserService userService;
    @ApiOperation(value = "获取当前登录用户的信息")
    @GetMapping("info")
    public ResultVo info(){
        //获取token
        TUser loginUser = MyContextHolder.get();
        return ResultVo.success("查看",loginUser);
    }
​
}

登录以后,我们能进行其他操作,比如能通过info获取用户,通过验证token是否失效来获取。

将token存在ThreadLocal中

public class MyContextHolder {
    static ThreadLocal<TUser> userHolder = new ThreadLocal<>();
​
    public static void set(TUser user){
        userHolder.set(user);
    }
    public static TUser get(){
        return userHolder.get();
    }
}

写一个过滤器,当访问其他页面的时候判断是否登录实现,验证token

package com.java2205.logindemo.filter;
​
​
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.java2205.logindemo.common.MyContextHolder;
import com.java2205.logindemo.entity.TUser;
import com.java2205.logindemo.service.TUserService;
import com.java2205.logindemo.util.JWTUtil;
import com.java2205.logindemo.util.ResponseUtil;
import com.java2205.logindemo.vo.ResultVo;
​
import org.springframework.beans.factory.annotation.Autowired;
​
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
​
/**
 * 
 */
@WebFilter("/tUser/*")
public class JWTAuthFilter implements Filter {
    @Autowired
    TUserService userService;
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //从请求头中获取token
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        String token = httpServletRequest.getHeader("Authorization");
        try{
            if(JWTUtil.verify(token)) {
                //成功了,从token中获取用户的信息
                String account = JWTUtil.getAccount(token);
                TUser loginuser = userService.getOne(new QueryWrapper<TUser>().eq("uname", account));
                MyContextHolder.set(loginuser);
​
                filterChain.doFilter(servletRequest,servletResponse);
            }else{
                ResponseUtil.writeJson(httpServletResponse,ResultVo.fail("用户没有登录,请先登录",null));
            }
        }catch (Exception e){
            if(e instanceof TokenExpiredException){
                //过期了
                String account = JWTUtil.getAccount(token);
                if(JWTUtil.createTokens(token)) {
                    Long time = (Long) JWTUtil.getToken(token);
​
​
                    if ((time + JWTUtil.EXPIREDMAX)-(System.currentTimeMillis()  ) >= 0) {
                        //换新的token,先清除老token
                        JWTUtil.remove(token);
                        String newToken = JWTUtil.createToken(account);
                        //新的时间
                        JWTUtil.saveToken(newToken, JWTUtil.currentTime());
                        //将新的token放入到头部中
                        httpServletResponse.setHeader("token", newToken);
                        //成功了,从token中获取用户的信息
                        TUser loginuser = userService.getOne(new QueryWrapper<TUser>().eq("uname", account));
                        MyContextHolder.set(loginuser);
                        //放行
                        filterChain.doFilter(servletRequest, servletResponse);
                    }else {
                        ResponseUtil.writeJson(httpServletResponse,ResultVo.fail("token过期,请重新登录",null));
                    }
                }else {
                    ResponseUtil.writeJson(httpServletResponse,ResultVo.fail("token过期",null));
                }
​
​
                
​
            }else{
                ResponseUtil.writeJson(httpServletResponse,ResultVo.fail("无效token,请重新登录",null));
            }
        }
​
    }
}

写一个返回josn格式

package com.java2205.logindemo.util;
​
import com.alibaba.fastjson.JSONObject;
​
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
​
/**
 *
 */
public class ResponseUtil {
​
    public static void writeJson(HttpServletResponse response,Object data){
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json");
        try {
            response.getWriter().write(JSONObject.toJSONString(data));
        } catch (IOException e) {
            e.printStackTrace();
        }
​
    }
}

写一个异常处理

@RestControllerAdvice
public class MyExceptionHandler {
    @ExceptionHandler(RuntimeException.class)
    public ResultVo handler(RuntimeException e){
        return ResultVo.fail(e.getMessage(),null);
    }
}

启动类加入

@SpringBootApplication
@ServletComponentScan("com.java2205.logindemo")
public class LogindemoApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(LogindemoApplication.class, args);
    }
​
}

完全目录

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值