admin 发表于 2024-9-7 22:02:36

SSM框架配置使用token与测试使用

1.导包在pom.xml中导入需要的依赖jar包,点击刷新下载<dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.10.0</version>
      </dependency>2.编写token的代码一般来说,在项目的文件夹下创建一个文件夹utils,在下面创建一个java文件JWTUtils。2个变量private static final long EXPIRE_TIME = 15 * 60 * 1000;//代表过期时间(15分钟),前端这么长时间没操作,就过期了,需要重新登录。
private static final String TOKEN_SECRET = “f26e587c28064d0e855e72c0a6a0e618”;//代表密钥,随便自己设置,越复杂越难被破解4个方法public static String sign(String username,String userId) //生成token,用户登录之后就调用这个方法。输入两个参数,一般是账号和密码
public static boolean verify(String token)//验证token,在每次访问接口的时候使用,一般在拦截器中使用(拦截器后面有)
public static String getUsername(String token) //通过token获取用户名
public static String getUserId(String token)//通过token获取用户id
一般一个设置为账号,一个设置为密码import com.auth0.jwt.*;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.io.UnsupportedEncodingException;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

/**

* Java web token 工具类

*


*/

public class JWTUtils {

    /**

   * 过期时间一天,

   * TODO 正式运行时修改为15分钟

   */

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

    /**

   * token私钥

   */

    private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";

    /**

   * 校验token是否正确

   *

   * @param token 密钥

   * @return 是否正确

   */

    public static boolean verify(String token) {
      try {
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm)
                  .build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
      } catch (Exception exception) {
            return false;
      }
    }
    /**
   * 获得token中的信息无需secret解密也能获得
   *
   * @return token中包含的用户名
   */
    public static String getUsername(String token) {
      try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("loginName").asString();
      } catch (JWTDecodeException e) {
            return null;
      }
    }
    /**
   * 获取登陆用户ID
   * @param token
   * @return
   */
    public static String getUserId(String token) {
      try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("userId").asString();
      } catch (JWTDecodeException e) {
            return null;
      }
    }
    /**
   * 生成签名,15min后过期
   *
   * @param username 用户名
   * @return 加密的token
   */
    public static String sign(String username,String userId) {
      Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);// 私钥及加密算法
      Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
      // 设置头部信息
      Map header = new HashMap<>(2);
      header.put("typ", "JWT");
      header.put("alg", "HS256");
      // 附带username,userId信息,生成签名
      return JWT.create()
                .withHeader(header)
                .withClaim("loginName", username)
                .withClaim("userId",userId)
                .withExpiresAt(date)
                .sign(algorithm);
    }

}3.编写拦截器代码token的作用是验证用户的登录信息,前端的每次http请求都需要检测用户是否登录。因此,需要编写拦截器的代码。在项目下面创建一个文件夹 interceptor,在里面创建TokenInterceptor.java文件,放入代码。
最重要的是preHandle方法,因为我前端传过来的token的名字叫sessionValue,所以我获取的是sessionValue,如果前端传来的token名字叫token,把下面代码String token=request.getParameter(“sessionValue”);中的sessionValue改为token。
如果通过验证,就为true,进入后端controller方法,如果没有通过,返回前端false。
如果没有token值传来,就是进行页面跳转到登陆页面。import com.alibaba.fastjson.JSONObject;
import com.lostAndFound.utils.JWTUtils;
import io.swagger.annotations.ApiResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
* 此处拦截器
*/
public class TokenInterceptor implements HandlerInterceptor {

    /**
   * 拦截器和过滤器的区别
   * 1.拦截器针对访问控制器进行拦截
   * 及 @RequestMapping(value = {"/test"})
   * 简而言说就是访问方法的url
   * 应用:可以作为权限的判断,
   * 2.过滤器则是针对全局的请求
   * 包括:css/js/html/jpg/png/git/...
   * 及静态文件
   *
   */

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      response.setCharacterEncoding("utf-8");
      String token=request.getParameter("sessionValue");
      //Cookie cookie=getCookieByName(request,"_COOKIE_NAME");
      //如果已经登录,不拦截
      if (null != token) {
            //验证token是否正确
            boolean result = JWTUtils.verify(token);
            System.out.println("是否通过拦截器:"+result);
            if (!result) {
                return false;
            }
            return true;
      }
      //如果没有登录,则跳转到登录界面
      else {
            //重定向 第一种 调用控制器 方法
            response.sendRedirect(request.getContextPath() + "/login");
            //重定向 第二种 重定向方法
            //            request.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(request, response);
            //            System.out.println(request.getContextPath());
            return false;
            /**
             * 以下是为了登录成功后返回到刚刚的操作,不跳到主界面
             * 实现:通过将请求URL保存到session的beforePath中,然后在登录时判断beforePath是否为空
             */
      }
    }

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

    /**
   * 根据名字获取cookie
   *
   * @param request
   * @param name    cookie名字
   * @return
   */
    public static Cookie getCookieByName(HttpServletRequest request, String name) {
      Map<String, Cookie> cookieMap = ReadCookieMap(request);
      if (cookieMap.containsKey(name)) {
            Cookie cookie =cookieMap.get(name);
            return cookie;
      } else {
            return null;
      }
    }
    /**
   * 将cookie封装到Map里面
   *
   * @param request
   * @return
   */
    private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request) {
      Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
      Cookie[] cookies = request.getCookies();
      if (null != cookies) {
            for (Cookie cookie : cookies) {
                cookieMap.put(cookie.getName(), cookie);
            }
      }
      return cookieMap;
    }

    /**
   * 返回信息给客户端
   *
   * @param response
   * @param out
   * @param apiResponse
   */
    private void responseMessage(HttpServletRequest request, HttpServletResponse response, PrintWriter out, ApiResponse apiResponse) throws IOException {
      response.setContentType("application/json; charset=utf-8");
      out.print(JSONObject.toJSONString(apiResponse));
      out.flush();
      out.close();
    }4.在配置文件中配置拦截器token的作用是验证用户的登录信息,前端的每次http请求都需要检测用户是否登录,但是登录的时候没有token,所以需要放行token。系统不知道什么时候需要拦截,什么时候不拦截。因此需要配置需要拦截的地址。配置在spring-mvc.xml文件中。(也有可能不叫spring-mvc.xml,不过名字一般和mvc,web有关,比如spring-web,在resources文件夹下面找找)
其中<mvc:mapping path=“/admin/**”/>代表要拦截的地址,我的所有方法都在admin下面,admin是controller层下面的文件夹。
<mvc:exclude-mapping path=“/admin/checkLogin”/>代表不需要token验证的方法,常见是登录
告诉系统拦截的的位置(前面第三点的位置)<!--&lt;!&ndash;自定义拦截器&ndash;&gt;-->
    <mvc:interceptors>
      <mvc:interceptor>
            <mvc:mapping path="/admin/**"/>
            <mvc:exclude-mapping path="/admin/checkLogin"/>
            <bean class="com.lostAndFound.interceptor.TokenInterceptor"></bean>
      </mvc:interceptor>
    </mvc:interceptors>5.测试登录的方法,前端传来账号密码,首先判断账号密码是否正确,正确创建token并返回,错误返回false
其他业务方法基本相同,因为在拦截器已经验证过token是否有效了,这里就不需要验证了。@RequestMapping(value = "/checkLogin")
    @ResponseBody
    public String checkLogin(@RequestParam() String username, @RequestParam() String password){

      Admin admin=new Admin();
      admin.setId(Integer.parseInt(username));
      admin.setPassword(password);
      boolean bool = adminService.checkAdminLog(admin);
      System.out.println("密码是否正确:"+bool);
      if(bool){
            //返回token值
            String token = JWTUtils.sign(username, password);
            System.out.println(token);
            return token;
      }
      else{
            return "false";
      }

活跃概况 发表于 2024-10-20 12:37:52

如果这就是爱,再转身的时候就该留下

活跃概况 发表于 2024-10-24 08:09:44

楼主听话,快到碗里来!

落花随流水 发表于 2024-10-25 07:32:26

楼主听话,快到碗里来!

风吹杨柳 发表于 2024-11-16 05:24:14

吊炸天的xx,调皮会死人的

风吹杨柳 发表于 2024-11-16 06:10:52

如果你智商能再高点,也许我会上当

杜冷丁 发表于 2024-11-27 20:57:44

水B楼主,经验拿好

青青小苗 发表于 2024-12-2 16:37:36

我的一楼总是献给度娘

紫露凝香 发表于 2024-12-2 23:53:00

闪瞎了我的钛合金狗眼

青春舞曲 发表于 2024-12-5 14:35:46

楼主你知道的太多了。
页: [1] 2 3
查看完整版本: SSM框架配置使用token与测试使用