可乐分享

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 439|回复: 19

[开发教程] SSM框架配置使用token与测试使用

[复制链接]

416

主题

2

回帖

1416

积分

管理员

Rank: 12Rank: 12Rank: 12

积分
1416
发表于 2024-9-7 22:02:36 | 显示全部楼层 |阅读模式
1.导包

在pom.xml中导入需要的依赖jar包,点击刷新下载

  1. <dependency>
  2.             <groupId>com.auth0</groupId>
  3.             <artifactId>java-jwt</artifactId>
  4.             <version>3.10.0</version>
  5.         </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
一般一个设置为账号,一个设置为密码

  1. import com.auth0.jwt.*;
  2. import com.auth0.jwt.algorithms.Algorithm;
  3. import com.auth0.jwt.exceptions.JWTDecodeException;
  4. import com.auth0.jwt.interfaces.DecodedJWT;

  5. import java.io.UnsupportedEncodingException;

  6. import java.util.Date;

  7. import java.util.HashMap;

  8. import java.util.Map;

  9. /**

  10. * Java web token 工具类

  11. *


  12. */

  13. public class JWTUtils {

  14.     /**

  15.      * 过期时间一天,

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

  17.      */

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

  19.     /**

  20.      * token私钥

  21.      */

  22.     private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";

  23.     /**

  24.      * 校验token是否正确

  25.      *

  26.      * @param token 密钥

  27.      * @return 是否正确

  28.      */

  29.     public static boolean verify(String token) {
  30.         try {
  31.             Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
  32.             JWTVerifier verifier = JWT.require(algorithm)
  33.                     .build();
  34.             DecodedJWT jwt = verifier.verify(token);
  35.             return true;
  36.         } catch (Exception exception) {
  37.             return false;
  38.         }
  39.     }
  40.     /**
  41.      * 获得token中的信息无需secret解密也能获得
  42.      *
  43.      * @return token中包含的用户名
  44.      */
  45.     public static String getUsername(String token) {
  46.         try {
  47.             DecodedJWT jwt = JWT.decode(token);
  48.             return jwt.getClaim("loginName").asString();
  49.         } catch (JWTDecodeException e) {
  50.             return null;
  51.         }
  52.     }
  53.     /**
  54.      * 获取登陆用户ID
  55.      * @param token
  56.      * @return
  57.      */
  58.     public static String getUserId(String token) {
  59.         try {
  60.             DecodedJWT jwt = JWT.decode(token);
  61.             return jwt.getClaim("userId").asString();
  62.         } catch (JWTDecodeException e) {
  63.             return null;
  64.         }
  65.     }
  66.     /**
  67.      * 生成签名,15min后过期
  68.      *
  69.      * @param username 用户名
  70.      * @return 加密的token
  71.      */
  72.     public static String sign(String username,String userId) {
  73.         Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);// 私钥及加密算法
  74.         Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
  75.         // 设置头部信息
  76.         Map header = new HashMap<>(2);
  77.         header.put("typ", "JWT");
  78.         header.put("alg", "HS256");
  79.         // 附带username,userId信息,生成签名
  80.         return JWT.create()
  81.                 .withHeader(header)
  82.                 .withClaim("loginName", username)
  83.                 .withClaim("userId",userId)
  84.                 .withExpiresAt(date)
  85.                 .sign(algorithm);
  86.     }

  87. }
复制代码
3.编写拦截器代码

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

  1. import com.alibaba.fastjson.JSONObject;
  2. import com.lostAndFound.utils.JWTUtils;
  3. import io.swagger.annotations.ApiResponse;
  4. import org.springframework.web.servlet.HandlerInterceptor;
  5. import org.springframework.web.servlet.ModelAndView;

  6. import javax.servlet.http.Cookie;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;

  9. import java.io.IOException;
  10. import java.io.PrintWriter;
  11. import java.util.HashMap;
  12. import java.util.Map;

  13. /**
  14. * 此处拦截器
  15. */
  16. public class TokenInterceptor implements HandlerInterceptor {

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

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

  57.     @Override
  58.     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  59.     }

  60.     @Override
  61.     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  62.     }

  63.     /**
  64.      * 根据名字获取cookie
  65.      *
  66.      * @param request
  67.      * @param name    cookie名字
  68.      * @return
  69.      */
  70.     public static Cookie getCookieByName(HttpServletRequest request, String name) {
  71.         Map<String, Cookie> cookieMap = ReadCookieMap(request);
  72.         if (cookieMap.containsKey(name)) {
  73.             Cookie cookie =  cookieMap.get(name);
  74.             return cookie;
  75.         } else {
  76.             return null;
  77.         }
  78.     }
  79.     /**
  80.      * 将cookie封装到Map里面
  81.      *
  82.      * @param request
  83.      * @return
  84.      */
  85.     private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request) {
  86.         Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
  87.         Cookie[] cookies = request.getCookies();
  88.         if (null != cookies) {
  89.             for (Cookie cookie : cookies) {
  90.                 cookieMap.put(cookie.getName(), cookie);
  91.             }
  92.         }
  93.         return cookieMap;
  94.     }

  95.     /**
  96.      * 返回信息给客户端
  97.      *
  98.      * @param response
  99.      * @param out
  100.      * @param apiResponse
  101.      */
  102.     private void responseMessage(HttpServletRequest request, HttpServletResponse response, PrintWriter out, ApiResponse apiResponse) throws IOException {
  103.         response.setContentType("application/json; charset=utf-8");
  104.         out.print(JSONObject.toJSONString(apiResponse));
  105.         out.flush();
  106.         out.close();
  107.     }
复制代码
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验证的方法,常见是登录
告诉系统拦截的的位置(前面第三点的位置)

  1. <!--&lt;!&ndash;  自定义拦截器  &ndash;&gt;-->
  2.     <mvc:interceptors>
  3.         <mvc:interceptor>
  4.             <mvc:mapping path="/admin/**"/>
  5.             <mvc:exclude-mapping path="/admin/checkLogin"/>
  6.             <bean class="com.lostAndFound.interceptor.TokenInterceptor"></bean>
  7.         </mvc:interceptor>
  8.     </mvc:interceptors>
复制代码
5.测试

登录的方法,前端传来账号密码,首先判断账号密码是否正确,正确创建token并返回,错误返回false
其他业务方法基本相同,因为在拦截器已经验证过token是否有效了,这里就不需要验证了。

  1. @RequestMapping(value = "/checkLogin")
  2.     @ResponseBody
  3.     public String checkLogin(@RequestParam() String username, @RequestParam() String password){

  4.         Admin admin=new Admin();
  5.         admin.setId(Integer.parseInt(username));
  6.         admin.setPassword(password);
  7.         boolean bool = adminService.checkAdminLog(admin);
  8.         System.out.println("密码是否正确:"+bool);
  9.         if(bool){
  10.             //返回token值
  11.             String token = JWTUtils.sign(username, password);
  12.             System.out.println(token);
  13.             return token;
  14.         }
  15.         else{
  16.             return "false";
  17.         }
复制代码



可乐分享 - 免责声明1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关
2、本站信息来自网络,版权争议与本站无关
3、本站发布的相关帖子文章仅限用于学习和研究目的,不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负
4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
5、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
6、可乐分享管理员和版主有权不事先通知发贴者而删除本文

回复

使用道具 举报

0

主题

590

回帖

894

积分

高级会员

Rank: 6Rank: 6

积分
894
发表于 2024-10-20 12:37:52 | 显示全部楼层
如果这就是爱,再转身的时候就该留下
回复

使用道具 举报

0

主题

590

回帖

894

积分

高级会员

Rank: 6Rank: 6

积分
894
发表于 2024-10-24 08:09:44 | 显示全部楼层
楼主听话,快到碗里来!
回复

使用道具 举报

0

主题

502

回帖

762

积分

高级会员

Rank: 6Rank: 6

积分
762
发表于 2024-10-25 07:32:26 | 显示全部楼层
楼主听话,快到碗里来!
回复

使用道具 举报

0

主题

548

回帖

831

积分

高级会员

Rank: 6Rank: 6

积分
831
发表于 2024-11-16 05:24:14 | 显示全部楼层
吊炸天的xx,调皮会死人的
回复

使用道具 举报

0

主题

548

回帖

831

积分

高级会员

Rank: 6Rank: 6

积分
831
发表于 2024-11-16 06:10:52 | 显示全部楼层
如果你智商能再高点,也许我会上当
回复

使用道具 举报

0

主题

608

回帖

921

积分

高级会员

Rank: 6Rank: 6

积分
921
发表于 2024-11-27 20:57:44 | 显示全部楼层
水B楼主,经验拿好
回复

使用道具 举报

0

主题

528

回帖

801

积分

高级会员

Rank: 6Rank: 6

积分
801
发表于 2024-12-2 16:37:36 | 显示全部楼层
我的一楼总是献给度娘
回复

使用道具 举报

0

主题

632

回帖

957

积分

高级会员

Rank: 6Rank: 6

积分
957
发表于 2024-12-2 23:53:00 | 显示全部楼层
闪瞎了我的钛合金狗眼
回复

使用道具 举报

0

主题

518

回帖

786

积分

高级会员

Rank: 6Rank: 6

积分
786
发表于 2024-12-5 14:35:46 | 显示全部楼层
楼主你知道的太多了。
回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【可乐分享www.keleshare.cn】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|可乐分享,站长交流 ( 苏ICP备2024109924号 )|网站地图

GMT+8, 2025-5-7 03:13 , Processed in 0.113573 second(s), 21 queries .

Powered by 可乐分享

© 2023-2024 keleshare.cn.

快速回复 返回顶部 返回列表