Springboot学习07 :验证用户登录token方式

一、Token使用流程

1、登录验证程序思路:

1、判断提交信息的有效性
2、判断用户及密码正确性
3、生成token添加或更新数据库
4、返回token信息给客户端

2、拦截器思路

1、获得客户端的token信息
2、对比客户端token数据库token信息
3、判断客户端token超时
4、判断放行与拦截

二、springboot验证用户

1、注入依赖

       <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

2、数据库准备

在这里插入图片描述

用户表保存用户信息
在这里插入图片描述

token表保存信息与userid

User实体类:

public class User {
    private int userid;
    private String name,password;
    public int getUserid() {
        return userid;
    }
    public void setUserid(int userid) {
        this.userid = userid;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [userid=" + userid + ", name=" + name + ", password=" + password + "]";
    }
}

Token实体类:

public class Token {
private int tokenid,userid,buildtime;
private String token;
public int getTokenid() {
    return tokenid;
}
public void setTokenid(int tokenid) {
    this.tokenid = tokenid;
}
public int getUserid() {
    return userid;
}
public void setUserid(int userid) {
    this.userid = userid;
}
public int getBuildtime() {
    return buildtime;
}
public void setBuildtime(int buildtime) {
    this.buildtime = buildtime;
}
public String getToken() {
    return token;
}
public void setToken(String token) {
    this.token = token;
}
@Override
public String toString() {
    return "Token [tokenid=" + tokenid + ", userid=" + userid + ", buildtime=" + buildtime + ", token=" + token + "]";
}
}

顺便来个Result信息类:

public class Result {
  private boolean flag=false;
  private String msg="";
  private String token="";
public boolean isFlag() {
    return flag;
}
public void setFlag(boolean flag) {
    this.flag = flag;
}
public String getMsg() {
    return msg;
}
public void setMsg(String msg) {
    this.msg = msg;
}
public String getToken() {
    return token;
}
public void setToken(String token) {
    this.token = token;
}
@Override
public String toString() {
    return "TokenResult [flag=" + flag + ", msg=" + msg + ", token=" + token + "]";
}

}

用户Mapper:

import org.apache.ibatis.annotations.Mapper;
import com.dahao.bean.User;
@Mapper
public interface UserMapper {
  void addUser(User user);
  void updataUser(User user);
  User findByUserId(int id);
  User findByUserName(String name);
}

Token Mapper:

import org.apache.ibatis.annotations.Mapper;
import com.dahao.bean.Token;
import com.dahao.bean.User;
@Mapper
public interface TokenMapper {
    void addToken(Token token);
    void updataToken(Token token);
    Token findByUserId(int userid);
}

3、拦截器

public class TokenInterceptor implements HandlerInterceptor {
    @Autowired
    private TokenMapper TokenMapper;
    //提供查询
    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {}
    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {}
    @Override
    public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
        //普通路径放行
        if ("/API/yanzheng".equals(arg0.getRequestURI()) || "/API/login".equals(arg0.getRequestURI())) {
            return true;}    

        //权限路径拦截
        arg1.setCharacterEncoding("UTF-8");
        PrintWriter resultWriter=arg1.getWriter();
        final String headerToken=arg0.getHeader("XW-Token");
        //判断请求信息
        if(null==headerToken||headerToken.trim().equals("")){
            resultWriter.write("你没有token,需要登录");
            return false;
        }
       //解析Token信息
        try {
            Claims claims = Jwts.parser().setSigningKey("dahao").parseClaimsJws(headerToken).getBody();
            String tokenUserId=(String)claims.get("userid");
            int itokenUserId=Integer.parseInt(tokenUserId);
            //根据客户Token查找数据库Token
            Token myToken=TokenMapper.findByUserId(itokenUserId );

            //数据库没有Token记录
             if(null==myToken) {
                 resultWriter.write("我没有你的token?,需要登录");
                 return false;
             }
             //数据库Token与客户Token比较
             if( !headerToken.equals(myToken.getToken()) ){
                 resultWriter.write("你的token修改过?,需要登录");
                 return false;
             }
             //判断Token过期
             Date tokenDate=(Date)claims.getExpiration();
             int chaoshi=(int)(new Date().getTime()-tokenDate.getTime())/1000;
             if(chaoshi>60*60*24*3){
                 resultWriter.write("你的token过期了?,需要登录");
                 return false;
             }

        } catch (Exception e) {
            e.printStackTrace();
            resultWriter.write("反正token不对,需要登录");
            return false;
        }
        //最后才放行
        return true;
    }
}

4、配置拦截器,需要注意bean注解

@Configuration
public class TokenConfiguration extends WebMvcConfigurerAdapter{
    @Bean
    TokenInterceptor tokenInterceptor() {
        return new TokenInterceptor();
        // 这个方法才能在拦截器中自动注入查询数据库的对象
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry ){
        registry.addInterceptor(tokenInterceptor()).addPathPatterns("/API/**");
        //配置生成器:添加一个拦截器,拦截路径为API以后的路径
    }
}

5、登录验证程序

@Controller
//可以换成@RestController
@RequestMapping("/API/")
//方便拦截API路径下的URL
public class MainControler {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private TokenMapper tokenmapper;
    @RequestMapping("/index")
    public String showindex() {
        return "index";
    }
    @RequestMapping("/login")
    public String showlogin() {
        return "login";
    }
    @ResponseBody
    @RequestMapping("/yanzheng")
    public Result yanzheng(User resqUser, HttpServletRequest request) {
        //创建返回信息对象
        Result result = new Result();
        //判断用户信息为空
        if ("".equals(resqUser.getName()) || "".equals(resqUser.getPassword())) {
            result.setMsg("传入的用户名/密码为空!");
            return result;
        }

        //根据客户用户名查找数据库的usre对象
        User myUser = userMapper.findByUserName(resqUser.getName());
        //判断用户不存在
        if (null == myUser) {
            result.setMsg("用户不存在");
            return result;
        }
        //判断用户不存在
        if (!resqUser.getPassword().equals(myUser.getPassword())) {
            result.setMsg("密码不正确");
            return result;
        }

        //根据数据库的用户信息查询Token
        Token token = tokenmapper.findByUserId(myUser.getUserid());
        //为生成Token准备
        String TokenStr = "";
        Date date = new Date();
        int nowtime = (int) (date.getTime() / 1000);
        //生成Token
        TokenStr = creatToken(myUser, date);
        if (null == token) {
            //第一次登陆
            token = new Token();
            token.setToken(TokenStr);
            token.setBuildtime(nowtime);
            token.setUserid(myUser.getUserid());
            tokenmapper.addToken(token);    
        }else{
            //登陆就更新Token信息
            TokenStr = creatToken(myUser, date);
            token.setToken(TokenStr);
            token.setBuildtime(nowtime);
            tokenmapper.updataToken(token);
        }
        //返回Token信息给客户端
        result.setFlag(true);
        result.setMsg("登录成功");
        result.setToken(TokenStr);
        return result;
    }
    //生成Token信息方法(根据有效的用户信息)
    private String creatToken(User user, Date date) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT") // 设置header
                .setHeaderParam("alg", "HS256").setIssuedAt(date) // 设置签发时间
                .setExpiration(new Date(date.getTime() + 1000 * 60 * 60 * 24 * 3))
                .claim("userid",String.valueOf(user.getUserid()) ) // 设置内容
                .setIssuer("lws")// 设置签发人
                .signWith(signatureAlgorithm, "dahao"); // 签名,需要算法和key
        String jwt = builder.compact();
        return jwt;
    }
}

猜你喜欢

转载自blog.csdn.net/xiaowenshuma/article/details/82974023
今日推荐