当前位置:   article > 正文

SSM(Spring+Springmvc+MyBatis)+ajax+JWT,实现登录JWT(token)认证获取权限_springmvc jwt

springmvc jwt

 本人最近钻研SpringMVC,都是学习感悟与个人看法,接受任何提问与建议,希望大家提出自己独特的见解,谢谢。

也可以进入我的b站主页,观看在线教程,视频中写出了当前文章中未出现的技术,而且在拦截器上也做出了许多改动,使用了两个拦截器来进行认证与权限;

微风梦之雫的个人空间_哔哩哔哩_bilibili

1-总体

2-首先是我们的pom.xml

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.apache.maven.plugins</groupId>
  5. <artifactId>maven-compiler-plugin</artifactId>
  6. <configuration>
  7. <source>8</source>
  8. <target>8</target>
  9. </configuration>
  10. </plugin>
  11. </plugins>
  12. </build>
  13. <packaging>war</packaging>
  14. <dependencies>
  15. <dependency>
  16. <groupId>org.springframework</groupId>
  17. <artifactId>spring-web</artifactId>
  18. <version>5.3.5</version>
  19. </dependency>
  20. <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
  21. <dependency>
  22. <groupId>org.springframework</groupId>
  23. <artifactId>spring-webmvc</artifactId>
  24. <version>5.3.5</version>
  25. </dependency>
  26. <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
  27. <dependency>
  28. <groupId>org.springframework</groupId>
  29. <artifactId>spring-context</artifactId>
  30. <version>5.3.5</version>
  31. </dependency>
  32. <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
  33. <dependency>
  34. <groupId>org.springframework</groupId>
  35. <artifactId>spring-core</artifactId>
  36. <version>5.3.5</version>
  37. </dependency>
  38. <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
  39. <dependency>
  40. <groupId>org.springframework</groupId>
  41. <artifactId>spring-beans</artifactId>
  42. <version>5.3.5</version>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.glassfish.web</groupId>
  46. <artifactId>jstl-impl</artifactId>
  47. <version>1.2</version>
  48. <!-- 去除依赖 -->
  49. <exclusions>
  50. <exclusion>
  51. <groupId>javax.servlet</groupId>
  52. <artifactId>servlet-api</artifactId>
  53. </exclusion>
  54. </exclusions>
  55. </dependency>
  56. <dependency>
  57. <groupId>javax.servlet</groupId>
  58. <artifactId>javax.servlet-api</artifactId>
  59. <version>3.1.0</version>
  60. <scope>provided</scope>
  61. </dependency>
  62. <dependency>
  63. <groupId>com.alibaba</groupId>
  64. <artifactId>fastjson</artifactId>
  65. <version>1.2.76</version>
  66. </dependency>
  67. <dependency>
  68. <groupId>c3p0</groupId>
  69. <artifactId>c3p0</artifactId>
  70. <version>0.9.1.2</version>
  71. </dependency>
  72. <dependency>
  73. <groupId>mysql</groupId>
  74. <artifactId>mysql-connector-java</artifactId>
  75. <version>8.0.20</version>
  76. </dependency>
  77. <dependency>
  78. <groupId>org.springframework</groupId>
  79. <artifactId>spring-jdbc</artifactId>
  80. <version>5.3.5</version>
  81. </dependency>
  82. <!-- https://mvnrepository.com/artifact/org.springframework/spring-websocket -->
  83. <dependency>
  84. <groupId>org.springframework</groupId>
  85. <artifactId>spring-websocket</artifactId>
  86. <version>5.3.5</version>
  87. </dependency>
  88. <dependency>
  89. <groupId>org.mybatis</groupId>
  90. <artifactId>mybatis-spring</artifactId>
  91. <version>1.3.0</version>
  92. </dependency>
  93. <dependency>
  94. <groupId>org.mybatis</groupId>
  95. <artifactId>mybatis</artifactId>
  96. <version>3.4.1</version>
  97. </dependency>
  98. <dependency>
  99. <groupId>org.slf4j</groupId>
  100. <artifactId>slf4j-api</artifactId>
  101. <version>1.7.25</version>
  102. </dependency>
  103. <dependency>
  104. <groupId>io.jsonwebtoken</groupId>
  105. <artifactId>jjwt</artifactId>
  106. <version>0.9.0</version>
  107. </dependency>
  108. <!--redis -->
  109. <!--spring-data-redis版本不能太高害怕有冲突 -->
  110. <dependency>
  111. <groupId>org.springframework.data</groupId>
  112. <artifactId>spring-data-redis</artifactId>
  113. <version>1.7.5.RELEASE</version>
  114. </dependency>
  115. <dependency>
  116. <groupId>redis.clients</groupId>
  117. <artifactId>jedis</artifactId>
  118. <version>2.9.0</version>
  119. </dependency>
  120. <dependency>
  121. <groupId>com.fasterxml.jackson.core</groupId>
  122. <artifactId>jackson-databind</artifactId>
  123. <version>2.11.4</version>
  124. </dependency>
  125. <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
  126. <dependency>
  127. <groupId>commons-codec</groupId>
  128. <artifactId>commons-codec</artifactId>
  129. <version>1.10</version>
  130. </dependency>
  131. </dependencies>

3-Configuration配置类

1.ServletConfig, 我们的一些拦截器,或者处理器,视图解析器,都可以在此配置类进行配置,它是实现了WebMvcConfigurer的方法;

  1. @Configuration
  2. @EnableWebMvc
  3. @ComponentScan(basePackages = "com.cjj.controller")
  4. public class ServletConfig implements WebMvcConfigurer {
  5. @Bean
  6. public ViewResolver viewResolver(){
  7. InternalResourceViewResolver viewResolver=new InternalResourceViewResolver();
  8. viewResolver.setPrefix("/WEB-INF/views/");
  9. viewResolver.setSuffix(".html");
  10. viewResolver.setExposeContextBeansAsAttributes(true);
  11. return viewResolver;
  12. //InternalResourceViewResolver 是 Spring MVC 中最常用的视图解析器
  13. // 它用于解析 JS P或 HTML 等资源文件。该解析器会将逻辑视图名称加上前缀和后缀
  14. // 例如将逻辑视图名称 “hello” 解析为 “/WEB-INF/views/hello.html”。
  15. }
  16. public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
  17. configurer.enable();
  18. }
  19. @Bean
  20. public MyInterceptor getMyInterceptor(){
  21. return new MyInterceptor();
  22. }
  23. public void addInterceptors(InterceptorRegistry registry) {
  24. registry.addInterceptor(getMyInterceptor())
  25. .addPathPatterns("/**")
  26. .excludePathPatterns("/login2")
  27. .excludePathPatterns("/")
  28. .excludePathPatterns("/testredis")
  29. .excludePathPatterns("/image/**")
  30. .excludePathPatterns("/js/**")
  31. .excludePathPatterns("/css/**");
  32. }
  33. }

2.RootConfig,用于配置我的数据库,完全实现用注解,xml文件不需要使用;

  1. @Configuration
  2. // Reposity @service @Bean
  3. @MapperScan(basePackages="com.cjj.Dao")
  4. @ComponentScan(basePackages = "com.cjj" ,excludeFilters =
  5. {@ComponentScan.Filter(type = FilterType.ANNOTATION,value ={EnableWebMvc.class, Controller.class})})
  6. //是除了web层的所有的Bean
  7. @PropertySource({"classpath:jdbc.properties"})
  8. public class RootConfig {
  9. @Value("${driverClass}")
  10. private String driver;
  11. @Value("${url}")
  12. private String url;
  13. @Value("${root}")
  14. private String root;
  15. @Value("${password}")
  16. private String password;
  17. @Bean(name="datasource")
  18. public DataSource getDataSource(){
  19. ComboPooledDataSource dataSource=new ComboPooledDataSource();
  20. try {
  21. dataSource.setDriverClass(driver);
  22. dataSource.setJdbcUrl(url);
  23. dataSource.setUser(root);
  24. dataSource.setPassword(password);
  25. } catch (PropertyVetoException e) {
  26. e.printStackTrace();
  27. }
  28. return dataSource;
  29. }
  30. @Bean(name = "jdbctemplate")
  31. public JdbcTemplate getJdbcTemplate(DataSource dataSource){
  32. JdbcTemplate jdbcTemplate=new JdbcTemplate(dataSource);
  33. return jdbcTemplate;
  34. }
  35. //mybatis的配置
  36. @Bean
  37. public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
  38. System.out.println("SqlSessionFactoryBean---------------------------");
  39. ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
  40. SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();//mybatis-plus插件类
  41. sqlSessionFactoryBean.setDataSource(getDataSource());//数据源
  42. sqlSessionFactoryBean.setMapperLocations(resourcePatternResolver.getResources("classpath:mappers/*.xml"));
  43. return sqlSessionFactoryBean;
  44. }
  45. }

让我们可以不需要配置xml文件,就能访问到mappers下的所有映射文件,jdbc.properties我就不献上了,大家根据自己的数据库配置来;

3. MvcApplication,实现我们的AbstractAnnotationConfigDispatcherServletInitializer,就不用多说了,用于配置我们的容器,很关键的一个容器类;

  1. public class MvcApplication extends AbstractAnnotationConfigDispatcherServletInitializer {
  2. @Override
  3. protected Class<?>[] getRootConfigClasses() {
  4. //返回的带有@Configuration注解的类用来配置ContextLoaderListener;
  5. System.out.println("RootConfig-----------");
  6. return new Class[]{RootConfig.class};
  7. }
  8. @Override
  9. protected Class<?>[] getServletConfigClasses() {
  10. //将一个或多个路径映射到DispatcherServlet上;
  11. System.out.println("ServletConfig-----------");
  12. return new Class[]{ServletConfig.class};
  13. }
  14. @Override
  15. protected String[] getServletMappings() {
  16. // /*拦截所有http请求,包括.jsp,都作为控制器类的请求路径处理;
  17. System.out.println("getServletMappings-----------");
  18. return new String[]{"/"};
  19. }
  20. }

4- 创建Model实体类

配置全都部署好了,接下来开始我们的实体类

User

  1. @Component
  2. public class User {
  3. private int id;
  4. private String username;
  5. private String password;
  6. private String token;
  7. private int rid;
  8. private List<privilege> pprivilegerList;
  9. public User() {
  10. }
  11. public User(String username, String password, String token) {
  12. this.username = username;
  13. this.password = password;
  14. this.token = token;
  15. }
  16. public User(int id, String username, String password, String token, int rid) {
  17. this.id = id;
  18. this.username = username;
  19. this.password = password;
  20. this.token = token;
  21. this.rid = rid;
  22. }
  23. public int getId() {
  24. return id;
  25. }
  26. public void setId(int id) {
  27. this.id = id;
  28. }
  29. public String getUsername() {
  30. return username;
  31. }
  32. public void setUsername(String username) {
  33. this.username = username;
  34. }
  35. public String getPassword() {
  36. return password;
  37. }
  38. public void setPassword(String password) {
  39. this.password = password;
  40. }
  41. public String getToken() {
  42. return token;
  43. }
  44. public void setToken(String token) {
  45. this.token = token;
  46. }
  47. public int getRid() {
  48. return rid;
  49. }
  50. public void setRid(int rid) {
  51. this.rid = rid;
  52. }
  53. public List<privilege> getPprivilegerList() {
  54. return pprivilegerList;
  55. }
  56. public void setPprivilegerList(List<privilege> pprivilegerList) {
  57. this.pprivilegerList = pprivilegerList;
  58. }
  59. @Override
  60. public String toString() {
  61. return "User{" +
  62. "id=" + id +
  63. ", username='" + username + '\'' +
  64. ", password='" + password + '\'' +
  65. ", token='" + token + '\'' +
  66. ", rid=" + rid +
  67. '}';
  68. }
  69. }

 Privilege,我的权限是用来测试的,我也不清楚,我的用法对不对,希望大家指点;

  1. @Component
  2. public class privilege {
  3. private int id;
  4. private String demoname;
  5. private int pid;
  6. public privilege() {
  7. }
  8. public privilege(int id, String demoname, int pid) {
  9. this.id = id;
  10. this.demoname = demoname;
  11. this.pid = pid;
  12. }
  13. public int getId() {
  14. return id;
  15. }
  16. public void setId(int id) {
  17. this.id = id;
  18. }
  19. public String getDemoname() {
  20. return demoname;
  21. }
  22. public void setDemoname(String demoname) {
  23. this.demoname = demoname;
  24. }
  25. public int getPid() {
  26. return pid;
  27. }
  28. public void setPid(int pid) {
  29. this.pid = pid;
  30. }
  31. }

5- 接口,实现映射

  1. @Repository
  2. @Mapper
  3. public interface UserDao {
  4. public User login(User user);
  5. public List<privilege> getprivilege(User user);
  6. }
  1. <mapper namespace="com.cjj.Dao.UserDao">
  2. <select id="login" parameterType="com.cjj.Model.User" resultType="com.cjj.Model.User">
  3. select id,username,password,token,rid FROM `user` where `user`.username=#{username} and `user`.`password`=#{password}
  4. </select>
  5. <resultMap id="wei" type="com.cjj.Model.privilege" >
  6. <id column="id" property="id"/>
  7. <result column="demoname" property="demoname"/>
  8. <result column="rid" property="rid"/>
  9. </resultMap>
  10. <select id="getprivilege" parameterType="com.cjj.Model.User" resultMap="wei">
  11. SELECT a.id ,b.demoname ,b.pid FROM user
  12. INNER JOIN role ON role.id = user.rid
  13. INNER JOIN privilege a ON a.id = role.id
  14. INNER JOIN privilege b on a.id = b.pid
  15. WHERE user.rid= #{rid}
  16. </select>
  17. </mapper>

6-创建业务方法,service

  1. public interface UserServiceIdao {
  2. public User login(User user);
  3. public List<privilege> getprivilege(User user);
  4. }

 实现接口

  1. @Service
  2. public class UserService implements UserServiceIdao {
  3. @Autowired
  4. private UserDao userDao;
  5. @Override
  6. public User login(User user) {
  7. return userDao.login(user);
  8. }
  9. @Override
  10. public List<privilege> getprivilege(User user) {
  11. return userDao.getprivilege(user);
  12. }
  13. }

7-JwtBuilder

在咱们进入控制层之前,咱们先来配置好jwt类的生成与解析

  1. public class JWTuuid {
  2. private static final long time =60*60*24*1000;
  3. private static final String signature="weifeng00000x";//秘钥
  4. public static final String createjwt(String name, User user)
  5. {
  6. JwtBuilder jwtBuilder= Jwts.builder();
  7. String jwttoken=jwtBuilder
  8. //header -- 设置头
  9. .setHeaderParam("typ","JWT")
  10. .setHeaderParam("alg","HS256")//加密算法
  11. //payload----载荷
  12. .claim("username",name)
  13. .claim("stu", user)
  14. //主题
  15. .setSubject("weifeng-test")
  16. //有效时间
  17. .setExpiration(new Date(System.currentTimeMillis()+time))//从当前开始,24小时
  18. //jwt id
  19. .setId(UUID.randomUUID().toString())
  20. //签名 signature
  21. .signWith(SignatureAlgorithm.HS256,signature)
  22. .compact();
  23. return jwttoken;
  24. }
  25. // 解析 JWT
  26. public static Claims testJWT(String jwt) {
  27. try{
  28. Claims claims = Jwts.parser()
  29. .setSigningKey(signature) //放入秘钥
  30. .parseClaimsJws(jwt) //放入需要解析的串
  31. .getBody();
  32. return claims;
  33. }catch (Exception e){
  34. e.printStackTrace();
  35. // 如果对于秘钥解析错误那么放回null
  36. return null;
  37. }
  38. }
  39. public static boolean validateToken(String token) {
  40. try {
  41. Jwts.parser().setSigningKey(signature).parseClaimsJws(token);
  42. return true;
  43. } catch (Exception e) {
  44. return false;
  45. }
  46. }
  47. }

8-Controller控制层

终于来到了咱们的控制层

  1. @RestController
  2. public class UserController {
  3. @Autowired
  4. UserService userService;
  5. @CrossOrigin(origins = "http://localhost:63342")
  6. @PostMapping("/login2")
  7. @ResponseBody
  8. public Object login2(@RequestBody JSONObject json, HttpServletRequest req, HttpServletResponse response)
  9. {
  10. String username=json.getString("username");
  11. String password=json.getString("password");
  12. User user =new User(username,password,"");
  13. System.out.println("username "+username+"-----pwd "+password);
  14. User login = userService.login(user);
  15. System.out.println("login的值为---------"+login);
  16. if(login!=null)
  17. {
  18. req.getSession().setAttribute("user",login);
  19. String createjwt = JWTuuid.createjwt(username, user);
  20. user.setToken(createjwt);
  21. System.out.println("jwt码--"+createjwt);
  22. // 将token写入响应头中
  23. response.addHeader("Authorization", "Bearer " + createjwt);
  24. response.setContentType("application/json;charset=utf-8");
  25. return createjwt;
  26. }
  27. else {
  28. String error="用户名或密码错误";
  29. // 设置HTTP状态码为401 Unauthorized
  30. response.setStatus(HttpStatus.UNAUTHORIZED.value(),"用户名或密码错误");
  31. //response.setStatus(HttpStatus.UNAUTHORIZED.value());
  32. response.setContentType("application/json;charset=utf-8");
  33. // 返回
  34. return error;
  35. }
  36. }
  37. @RequestMapping(value = "/aa",method = RequestMethod.GET)
  38. public ModelAndView getaa(HttpServletRequest req)
  39. {
  40. System.out.println("进来这个方法 getaa()");
  41. ModelAndView mv=new ModelAndView();
  42. mv.setViewName("aa");
  43. return mv;
  44. }
  45. @GetMapping("/demo")
  46. @ResponseBody
  47. public Object getstu(@RequestParam("demo") int demo,HttpServletRequest req){
  48. System.out.println("进来这个方法 getstu()");
  49. System.out.println("demo : "+demo);
  50. // System.out.println("token: "+token);
  51. // Claims claims=JWTuuid.testJWT(token);
  52. // if(claims==null){
  53. // System.out.println("jwt码有误,勿扰");
  54. // return "jwt码有误,勿扰";
  55. // }
  56. List<privilege> user = userService.getprivilege((User) req.getSession().getAttribute("user"));
  57. for (privilege s : user) {
  58. System.out.println(s.getDemoname());
  59. }
  60. // String obj=claims.getSubject();
  61. // System.out.println("提交主题:"+obj);
  62. return user;
  63. }
  64. }

其实我的登录是有些问题的,我返回的直接是个字符串,照理说应该是一个result集合,然后给状态或是其他什么的,将就看看吧,哈哈;

9-HandlerInterceptor拦截器

  1. public class MyInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. System.out.println("===============请求处理前(1)===================");
  5. String path=request.getRequestURL().toString();
  6. if(path.indexOf("/login2")>=0){
  7. System.out.println("确实是login方法------");
  8. return true;
  9. }
  10. System.out.println("--------------------------------------"+path);
  11. Object obj=request.getSession().getAttribute("user");
  12. System.out.println(obj+"---------------------MyInterceptor");
  13. if(obj!=null)
  14. return true;
  15. // 获取Authorization请求头中的token
  16. String authHeader = request.getHeader("Authorization");
  17. if (authHeader != null && authHeader.startsWith("Bearer ")) {
  18. String token = authHeader.substring(7);
  19. System.out.println("截取的token");
  20. // 验证token
  21. if (JWTuuid.validateToken(token)) {
  22. return true; // 验证通过,继续执行后续操作
  23. }
  24. }
  25. //request.setAttribute("msg","还没有登陆,请先登录");
  26. request.getRequestDispatcher("index.html").forward(request,response);
  27. return false;
  28. }
  29. @Override
  30. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  31. // HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
  32. System.out.println("===============请求处理后,生成视图之前(2)===================");
  33. //assert modelAndView != null;
  34. // System.out.println("modelviewname============="+modelAndView.getViewName());
  35. }
  36. @Override
  37. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  38. // HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
  39. System.out.println("===============结束时调用(3)===================");
  40. }
  41. }

我觉得我的拦截器,写的有问题,虽然能成功使用,但还是希望大家提出各自独特的见解;

10-前端界面

index.html

  1. <html>
  2. <head>
  3. <meta charset="UTF-8">
  4. <title>$Title$</title>
  5. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  6. </head>
  7. <body>
  8. 用户:<input id="username" type="text" name="username" placeholder="请输入用户">
  9. 密码:<input id="password" type="password" name="password" placeholder="请输入密码">
  10. <button id="login" value="登录"/>
  11. 登录
  12. <button type="reset" value="重置"/>
  13. 重置
  14. <script>
  15. $("#login").click(function (){
  16. let username = document.getElementById("username").value;
  17. let password = document.getElementById("password").value;
  18. let user={};
  19. user.username=username;
  20. user.password=password;
  21. console.log(user);
  22. $.ajax({
  23. url: 'http://localhost:9090/login2', // 请求的API接口地址
  24. //http://iwenwiki.com:8088/api/FingerUnion/list.php
  25. type: 'POST',
  26. // headers:{
  27. // token:"wawa"
  28. // },
  29. dataType: 'text',
  30. contentType:"application/json",
  31. data:JSON.stringify(user) ,
  32. success: function (e) {
  33. alert("key为:"+e);
  34. console.log("key为:"+e);
  35. localStorage.setItem('token', e);
  36. sessionStorage.setItem('token',e);
  37. window.location.href="http://localhost:9090/aa";
  38. // TODO: 处理接收到的数据
  39. },
  40. error: function (e) {
  41. alert("账号或密码错误!!");
  42. }
  43. });
  44. });
  45. // let p=new Promise((resolve, reject) =>{
  46. </script>
  47. </body>
  48. </html>

aa.html    拿到当前用户的操作权限的

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  7. </head>
  8. <body>
  9. <p id="pp">你好你好你好你好喝牛奶</p>
  10. 操作功能:<button type="button" id="caoz" value="请操作"/>
  11. </body>
  12. </html>
  13. <script>
  14. $("#caoz").click(function (){
  15. $.ajax({
  16. url: 'http://localhost:9090/demo', // 请求的API接口地址
  17. type:"get",
  18. dataType: 'json',
  19. contentType:"application/json",
  20. data:{
  21. demo:20040309,
  22. },
  23. headers:{
  24. "Authorization":localStorage.getItem('token'),
  25. },
  26. success:function (e){
  27. alert("success回调执行了")
  28. for(var i = 0; i < e.length; i++) {
  29. var name = e[i].demoname;
  30. console.log("权限有", name);
  31. }
  32. },
  33. error:function (e){
  34. alert("error回调执行了")
  35. },
  36. });
  37. })
  38. </script>

到此,我个人学习的收获就完了,希望能看到这里的朋友,学习永无瓶颈,天天开心,一直保持着一颗追求新技术的心。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/182331
推荐阅读
相关标签
  

闽ICP备14008679号