【转】java基于token验证之登陆验证

转自博客 https://blog.csdn.net/weixin_39102174/article/details/90411116

以上博主讲的更清除些,此博客是为了自己加深记忆。

对于前后端分离的项目来说session来判断是否登陆实现比较困难,token是比较好的方式。

大概流程:

1.用户登陆,若成功则后台生成一个token,并把此token返回给客户端浏览器

2.客户端接收到token后,每次请求都要把此token放到header中发给后段

3.后段使用拦截器判断token的正确性和实效性。

以下是具体代码:

Token工具类:

  1. package com.sign;
  2.  import com.auth0.jwt.JWT;
  3.  

    import com.auth0.jwt.JWTVerifier;

  4.  

    import com.auth0.jwt.algorithms.Algorithm;

  5.  

    import com.auth0.jwt.exceptions.JWTDecodeException;

  6.  

    import com.auth0.jwt.interfaces.DecodedJWT;

  7.  

  8.  

    import java.util.Date;

  9.  

    import java.util.HashMap;

  10.  

    import java.util.Map;

  11.  

  12.  

    public class TokenSign {

  13.  

  14.  

    /**

  15.  

    * 过期时间60分钟

  16.  

    */

  17.  

    private static final long EXPIRE_TIME=60 * 60 *1000;

  18.  

  19.  

    /**

  20.  

    * 私钥,使用它生成token,最好进行下加密

  21.  

    */

  22.  

    private static final String TOKEN_SECRET="Token";

  23.  

  24.  

  25.  

    /**

  26.  

    * 产生token

  27.  

    * @param useName

  28.  

    * @param userId

  29.  

    * @return

  30.  

    */

  31.  

    public static String sign(String useName,String userId){

  32.  

  33.  

    try{

  34.  

  35.  

    //设置15分钟失效

  36.  

    Date date=new Date(System.currentTimeMillis()+EXPIRE_TIME);

  37.  

    //私钥及加密算法

  38.  

    Algorithm algorithm=Algorithm.HMAC256(TOKEN_SECRET);

  39.  

    //设置头部信息

  40.  

    Map<String,Object> header=new HashMap<>();

  41.  

    header.put("typ","JWT");

  42.  

    header.put("alg","HS256");

  43.  

    //附带username和userid信息,存储到token中,生成签名

  44.  

    return JWT.create()

  45.  

    .withHeader(header)

  46.  

    //存储自己想要留存给客户端浏览器的内容

  47.  

    .withClaim("userName",useName)

  48.  

    .withClaim("userId",userId)

  49.  

    .withExpiresAt(date)

  50.  

    .sign(algorithm);

  51.  

  52.  

  53.  

  54.  

    }catch (Exception e){

  55.  

    e.printStackTrace();

  56.  

    }

  57.  

  58.  

    return null;

  59.  

    }

  60.  

  61.  

  62.  

    /**

  63.  

    * token校验是否正确

  64.  

    * @param token

  65.  

    * @return

  66.  

    */

  67.  

  68.  

    public static boolean verify(String token){

  69.  

  70.  

    try {

  71.  

    Algorithm algorithm=Algorithm.HMAC256(TOKEN_SECRET);

  72.  

  73.  

    JWTVerifier verifier =JWT.require(algorithm).build();

  74.  

    //此方法若token验证失败会抛错的,所以直接return true没问题

  75.  

    DecodedJWT decodedJWT =verifier.verify(token);

  76.  

    return true;

  77.  

    }catch (Exception e){

  78.  

    e.printStackTrace();

  79.  

    }

  80.  

  81.  

    return false;

  82.  

    }

  83.  

  84.  

  85.  

    /**

  86.  

    * 获取token中信息 userName

  87.  

    * @param token

  88.  

    * @return

  89.  

    */

  90.  

    public static String getUsername(String token) {

  91.  

    try {

  92.  

    DecodedJWT jwt = JWT.decode(token);

  93.  

    return jwt.getClaim("userName").asString();

  94.  

    } catch (JWTDecodeException e) {

  95.  

    e.getStackTrace();

  96.  

    }

  97.  

    return null;

  98.  

    }

  99.  

  100.  

  101.  

    /**

  102.  

    * 获取token中信息 userId

  103.  

    * @param token

  104.  

    * @return

  105.  

    */

  106.  

    public static String getUserId(String token) {

  107.  

    try {

  108.  

    DecodedJWT jwt = JWT.decode(token);

  109.  

    return jwt.getClaim("userId").asString();

  110.  

    } catch (JWTDecodeException e) {

  111.  

    e.getStackTrace();

  112.  

  113.  

    }

  114.  

    return null;

  115.  

    }

  116.  

  117.  

  118.  

    }

拦截器:

  1. package com.interceptor;

  2.  

  3.  

    import com.alibaba.fastjson.JSONObject;

  4.  

    import com.constant.TokenConstant;

  5.  

    import com.sign.TokenSign;

  6.  

    import org.springframework.stereotype.Component;

  7.  

    import org.springframework.web.servlet.HandlerInterceptor;

  8.  

    import org.springframework.web.servlet.ModelAndView;

  9.  

  10.  

    import javax.servlet.http.HttpServletRequest;

  11.  

    import javax.servlet.http.HttpServletResponse;

  12.  

    import java.util.HashMap;

  13.  

    import java.util.Map;

  14.  

  15.  

  16.  

    @Component

  17.  

    public class LoginInterceptor implements HandlerInterceptor {

  18.  

  19.  

  20.  

    // 在请求处理之前调用,只有返回true才会执行要执行的请求

  21.  

    @Override

  22.  

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {

  23.  

  24.  

    httpServletResponse.setCharacterEncoding("UTF-8");

  25.  

    String token=httpServletRequest.getHeader("accessToken");

  26.  

    if (null==token){

  27.  

    Map<String,Object> map=new HashMap<>();

  28.  

    map.put("data","token is null");

  29.  

    map.put("code","401");

  30.  

    httpServletResponse.getWriter().write(JSONObject.toJSONString(map));

  31.  

    return false;

  32.  

    }else {

  33.  

    boolean result= TokenSign.verify(token);

  34.  

  35.  

    if (result){

  36.  

    //更新存储的token信息

  37.  

    TokenConstant.updateTokenMap(token);

  38.  

    return true;

  39.  

    }

  40.  

  41.  

    Map<String,Object> map=new HashMap<>();

  42.  

    map.put("data","token is null");

  43.  

    map.put("code","401");

  44.  

    httpServletResponse.getWriter().write(JSONObject.toJSONString(map));

  45.  

    return false;

  46.  

  47.  

    }

  48.  

  49.  

  50.  

    }

  51.  

  52.  

    // 试图渲染之后执行

  53.  

    @Override

  54.  

    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

  55.  

  56.  

    }

  57.  

  58.  

    // 在请求处理之后,视图渲染之前执行

  59.  

    @Override

  60.  

    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

  61.  

  62.  

    }

  63.  

  64.  

  65.  

    }

  1. package com.constant;

  2.  

  3.  

    import java.util.HashMap;

  4.  

    import java.util.Map;

  5.  

  6.  

    public class TokenConstant {

  7.  

  8.  

    private static Map<String,String> map=new HashMap();

  9.  

  10.  

  11.  

    public static String getToken(){

  12.  

    return map.get("token");

  13.  

    }

  14.  

  15.  

    public static void updateTokenMap(String token){

  16.  

    map.put("token",token);

  17.  

    }

  18.  

  19.  

  20.  

    }

注册拦截器:

  1. package com.adapter;

  2.  

  3.  

    import com.interceptor.LoginInterceptor;

  4.  

    import org.springframework.beans.factory.annotation.Autowired;

  5.  

    import org.springframework.context.annotation.Configuration;

  6.  

    import org.springframework.web.servlet.config.annotation.CorsRegistry;

  7.  

    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

  8.  

    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

  9.  

    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

  10.  

  11.  

  12.  

    @Configuration

  13.  

    public class LoginAdapter implements WebMvcConfigurer {

  14.  

  15.  

  16.  

    //解决跨域问题

  17.  

    @Override

  18.  

    public void addCorsMappings(CorsRegistry registry) {

  19.  

    registry.addMapping("/**")

  20.  

    .allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")

  21.  

    .allowedMethods("*")

  22.  

    .allowedOrigins("*")

  23.  

    //是否允许使用cookie

  24.  

    .allowCredentials(true);

  25.  

    }

  26.  

  27.  

  28.  

  29.  

  30.  

    @Autowired

  31.  

    private LoginInterceptor loginInterceptor;

  32.  

  33.  

  34.  

    // 这个方法是用来配置静态资源的,比如html,js,css,等等

  35.  

    @Override

  36.  

    public void addResourceHandlers(ResourceHandlerRegistry registry) {

  37.  

    }

  38.  

  39.  

  40.  

  41.  

    // 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效

  42.  

    @Override

  43.  

    public void addInterceptors(InterceptorRegistry registry) {

  44.  

    System.out.println("进入拦截器");

  45.  

    //addPathPatterns是表明拦截哪些请求

  46.  

    //excludePathPatterns是对哪些请求不做拦截

  47.  

    registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/user/login");

  48.  

    }

  49.  

  50.  

    }

以上是后台的配置,除了登陆所有请求都会进行token验证。

前端代码概要:

前端用的VUE

  1. <template>

  2.  

    <div class="login">

  3.  

    <!--打包时用这个-->

  4.  

    <div class="welcome"><img src="/dist/static/image/welcome.png"></div>

  5.  

    <!--本地用这个-->

  6.  

    <!--<div class="welcome"><img src="/static/image/welcome.png"></div>-->

  7.  

    <div class="login-form">

  8.  

    <div class="login-inp"><label>账号</label><input type="text" placeholder="请输入账号" v-model="user.account"></div>

  9.  

    <div class="login-inp"><label>密码</label><input type="password" placeholder="请输入密码" v-model="user.password"></div>

  10.  

  11.  

    <div class="login-inp" v-show="!loadingShow" v-on:click="ok()">

  12.  

    <input type="button" value="立即登录" />

  13.  

    </div>

  14.  

    </div>

  15.  

    <!--加载效果-->

  16.  

    <wv-loadmore v-show="this.loadingShow"></wv-loadmore>

  17.  

  18.  

  19.  

    </div>

  20.  

    </template>

  21.  

  22.  

    <script>

  23.  

    import Vue from ‘vue‘;

  24.  

    import Axios from ‘axios‘

  25.  

    import { Toast } from ‘we-vue‘

  26.  

    export default {

  27.  

    name: ‘Login‘,

  28.  

    data: function () {

  29.  

    return {

  30.  

    user: {account: ‘‘, password: ‘‘},

  31.  

    show: false,

  32.  

    url:this.GLOBAL.loginUrl,

  33.  

    isDisable:false,

  34.  

    loadingShow:false

  35.  

    }

  36.  

    },

  37.  

    methods: {

  38.  

    ok: function () {

  39.  

    if (!this.user.account || !this.user.password) {

  40.  

    // Toast.loading(‘加载中‘);

  41.  

    Toast.text(‘请完善登陆信息‘);

  42.  

    console.log(‘param not allow null‘)

  43.  

    return

  44.  

    };

  45.  

  46.  

    this.isDisable=true;

  47.  

    this.loadingShow=true;

  48.  

  49.  

  50.  

  51.  

  52.  

    setTimeout(() => {

  53.  

  54.  

    Axios.post(this.url,

  55.  

    this.user,

  56.  

    { //方式2通过transformRequest方法发送数据,本质还是将数据拼接成字符串

  57.  

    transformRequest:[

  58.  

    function(data){

  59.  

    let params=‘‘;

  60.  

    for(let index in data){

  61.  

    params+=index+‘=‘+data[index]+‘&‘;

  62.  

    }

  63.  

    return params;

  64.  

    }

  65.  

    ]

  66.  

    })

  67.  

    .then(response => {

  68.  

    if (response.data) {

  69.  

    //存储token

  70.  

    localStorage.setItem(‘accessToken‘, response.data);

  71.  

    this.$router.push({ path: ‘home‘ })

  72.  

    }else {

  73.  

    Toast.fail(‘登陆失败‘);

  74.  

    console.log(‘登陆失败:‘, response.data.message)

  75.  

    }

  76.  

    this.loadingShow=false;

  77.  

    this.isDisable=false;

  78.  

    })

  79.  

    .catch(error => {

  80.  

    Toast.fail(‘请求失败‘);

  81.  

    console.log(‘请求失败:‘, error)

  82.  

    this.loadingShow=false;

  83.  

    this.isDisable=false;

  84.  

    })

  85.  

  86.  

    }, 1000)

  87.  

  88.  

  89.  

  90.  

  91.  

  92.  

  93.  

    },

  94.  

    cancel: function () {

  95.  

    this.show = false

  96.  

    this.$emit(‘cancel‘, this.flowParam)

  97.  

    }

  98.  

  99.  

    }

  100.  

    }

  101.  

  102.  

    </script>

  103.  

登陆界面最主要的是:localStorage.setItem(‘accessToken‘, response.data);把token信息存储

每次请求都放到header中:

此处简写:

  1. Axios.post(this.addUrl,param,

  2.  

    {headers: {‘Content-Type‘:‘application/json;charset=UTF-8‘,‘accessToken‘:localStorage.getItem(‘accessToken‘)}},

  3.  

    {method: ‘put‘}

  4.  

    ).then(response => {

localStorage.getItem(‘accessToken‘);获取存储在localStorage中的token信息

原文地址:https://www.cnblogs.com/EarlyBridVic/p/12532658.html

时间: 2024-10-08 22:24:09

【转】java基于token验证之登陆验证的相关文章

WebApi基于Token和签名的验证

最近一段时间在学习WebApi,涉及到验证部分的一些知识觉得自己并不是太懂,所以来博客园看了几篇博文,发现一篇讲的特别好的,读了几遍茅塞顿开(都闪开,我要装逼了),刚开始读有些地方不理解,所以想了很久,因此对原文中省略的部分这里做一点个人的理解和补充,非常基础,知道的园友就不需要了,只是帮助初次学习的园友理解.原文传送门: http://www.cnblogs.com/MR-YY/p/5972380.html#!comments 本篇博文中的所有代码均来自上述链接,如果你觉得有帮助,请点击链接给

Java实现token的生成与验证-登录功能

一.token与cookie相比较的优势1.支持跨域访问,将token置于请求头中,而cookie是不支持跨域访问的: 2.无状态化,服务端无需存储token,只需要验证token信息是否正确即可,而session需要在服务端存储,一般是通过cookie中的sessionID在服务端查找对应的session: 3.无需绑定到一个特殊的身份验证方案(传统的用户名密码登陆),只需要生成的token是符合我们预期设定的即可: 4.更适用于移动端(Android,iOS,小程序等等),像这种原生平台不支

JAVA中的Token 基于Token的身份验证

来源:转载 最近在做项目开始,涉及到服务器与安卓之间的接口开发,在此开发过程中发现了安卓与一般浏览器不同,安卓在每次发送请求的时候并不会带上上一次请求的SessionId,导致服务器每次接收安卓发送的请求访问时都新建一个Session进行处理,无法通过传统的绑定Session来进行保持登录状态和通讯状态. 基于传统方法无法判断安卓的每次请求访问状态,故查询资料了解到Token,特殊的身份证验证.以下是网上搜寻资料所得,作为学习总结资料. 令牌是一种能够控制站点占有媒体的特殊帧,以区别数据帧及其他

App登陆java后台处理和用户权限验证

最近做一个app项目,后台我独自一人开发,开发任务顺序安排上没有把登陆,注册和权限验证这些基本功能放在第一阶段开发,现在是部分业务相关功能已经完成,但是用户入口竟然还没有,只能说明当初需求分析的时候还是太过于着急了,把最基本的用户入口给放到后面了. 现在就需要在现有代码的基础上添加用户登录和权限验证功能. 关于登录和权限验证方面,参照以前做iOS的开发经验,App端提供用户名和密码换取token,每次通过换取的token请求需要登陆权限的操作. 现在反过来,我就需要考虑下面几个问题: 1.在现有

基于Token的身份验证——JWT(转)

本文转自:http://www.cnblogs.com/zjutzz/p/5790180.html 感谢作者 初次了解JWT,很基础,高手勿喷.基于Token的身份验证用来替代传统的cookie+session身份验证方法中的session. JWT是啥? JWT就是一个字符串,经过加密处理与校验处理的字符串,形式为: A.B.C A由JWT头部信息header加密得到B由JWT用到的身份验证信息json数据加密得到C由A和B加密得到,是校验部分 怎样生成A? header格式为: { "typ

WebApi_基于Token的身份验证——JWT(z)

基于Token的身份验证——JWT JWT是啥? JWT就是一个字符串,经过加密处理与校验处理的字符串,形式为: A.B.C A由JWT头部信息header加密得到B由JWT用到的身份验证信息json数据加密得到C由A和B加密得到,是校验部分 怎样生成A? header格式为: { "typ": "JWT", "alg": "HS256" } 它就是一个json串,两个字段是必须的,不能多也不能少.alg字段指定了生成C的算法

java web程序 登陆验证页面 4个页面人性化设置

到这里,快期末考试了,老师不讲课,我心里有苦不想说,也许没有考虑到老师的感受,让老师难堪了 但是我的行为已不再是我可以做的了.不可能了,我只是职业性的机械的做事了. 思路: 1.第一个是form表单,用户输入用户名和密码,点击登陆按钮 a.jsp 2.第二是验证页面,如果不是那个用户名和密码,则显示登陆失败或错误,点击链接重新登陆ok.jsp d.jsp 3.当用户为输入任何数据,即为空的时候,则提示用户先登录,c.jsp 第一个页面,就不写了 验证页面 ok.jsp ? 1 2 3 4 5 6

【Java EE 学习第70天】【数据采集系统第二天】【数据加密处理】【登陆验证】【登陆拦截器】【新建调查】【查询调查】

一.数据加密处理 这里使用MD5加密处理,使用java中自带加密工具类MessageDigest. 该类有一个方法digest,该方法输入参数是一个字符串返回值是一个长度为16的字节数组.最关键的是需要将这个16位的字节数组转换成为32位的字符串,转换方法是使用位移+与运算.将高四位移到低四位&0X0F得到一个字符,直接使用该值&0X0F得到一个字符,这样一个8bit的字节就能够拆成2个字符.最终16Byte就能够转换成为32个字符. 1 package com.kdyzm.utils;

基于 Token 的身份验证方法

使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录.大概的流程是这样的: 客户端使用用户名跟密码请求登录 服务端收到请求,去验证用户名与密码 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端