zoukankan      html  css  js  c++  java
  • springboot+jwt

    大概了解下SpringMVC和jwt,百度

     代码:

    1.整体框架

    2.controller

    package com.yiyezhiqiu.jwt.jwt.controller;


    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.alibaba.fastjson.JSONPObject;
    import com.yiyezhiqiu.jwt.jwt.annotation.LoginAnnotation;
    import com.yiyezhiqiu.jwt.jwt.annotation.OtherPermit;
    import com.yiyezhiqiu.jwt.jwt.domain.Users;
    import com.yiyezhiqiu.jwt.jwt.service.IUsersService;
    import com.yiyezhiqiu.jwt.jwt.service.impl.GetToken;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;

    import javax.annotation.Resource;

    /**
    * 实现jwt,token验证
    * 业务需求:没有登陆成功,不能访问其他页面,当登陆成功后,带入成功后返回给前端的token来访问其他页面
    * 实现:
    * 1.了解springMVC,mvc在实现时有处理controller,那么我们在处理controller前对路径进行拦截,实现WebMvcConfigure接口。
    * 2.拦截处理:实现HandlerInterceptor接口 ,在实现类中对请求的token进行验证。
    *
    *
    * 具体做法:
    * 1.springboot整合mybatis,跑通能查数据库
    * 2.写一个拦截处理器,即实现HandlerInterceptor接口
    * 2.1:思路
    * 对登陆操作不进行token验证,对非登陆操作要进行token验证
    * 2.2:做法
    * 2.2.1:写两个注解,一个是用来对登陆进行控制,一个是其他页面进行控制
    * 2.2.2:开始写MyInterceptor中代码
    *
    *
    * 3.实现WebMvcConfigure接口,对所有路径进行拦截,并把拦截器处理器实例加进来-》也就是实现拦截后使用拦截处理器去处理
    *
    *
    *
    *
    *
    */

    @Slf4j
    @RestController
    @RequestMapping(value = "/users")
    public class UsersController {

    @Autowired
    IUsersService usersService;
    @Resource(name = "GetToken")
    GetToken getToken;

    JSONObject jsonObject = new JSONObject();


    /**
    * 注册
    */
    @RequestMapping(value = "/register",method = RequestMethod.POST,produces = "application/json")
    public JSONObject register(@RequestBody Users users){

    int result = usersService.saveUsers(users);
    if(result >0){
    jsonObject.put("status",true);
    jsonObject.put("message","新增成功");
    return jsonObject;
    }else{
    jsonObject.put("status",false);
    jsonObject.put("message","新增失败");
    return jsonObject;
    }
    }


    /**
    * 登陆
    * @param users
    * @return
    */
    @LoginAnnotation
    @RequestMapping(value = "/login",method = RequestMethod.POST,produces = "application/json")
    public JSONObject usersLogin(@RequestBody Users users){

    log.info("userName;"+users.getUserName()+",password:"+users.getPassword());

    int result = usersService.findUsers(users);
    if(result >0){
    String token = getToken.token(users);
    jsonObject.put("users",users);
    jsonObject.put("message",token);

    }else{
    jsonObject.put("message","帐号或者密码错误");
    }
    return jsonObject;
    }

    /**
    * 其他页面
    * @return
    */
    @OtherPermit
    @RequestMapping(value = "/otherPage",method = RequestMethod.GET)
    public JSONObject otherPage(){
    //模仿下登陆后,传入token,token验证后返回有效信息
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("message","验证成功");
    jsonObject.put("code",200);
    return jsonObject;
    }


    }

     3.service:

      3.1 IUserService

    package com.yiyezhiqiu.jwt.jwt.service;

    import com.yiyezhiqiu.jwt.jwt.domain.Users;

    public interface IUsersService {

    public int saveUsers(Users users);

    public int findUsers(Users users);

    }
     3.2 impl下的UsersServiceImpl
    package com.yiyezhiqiu.jwt.jwt.service.impl;

    import com.yiyezhiqiu.jwt.jwt.dao.UsersDao;
    import com.yiyezhiqiu.jwt.jwt.domain.Users;
    import com.yiyezhiqiu.jwt.jwt.service.IUsersService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;

    import java.util.HashMap;
    import java.util.Map;
    @Service
    public class UsersServiceImpl implements IUsersService {

    @Autowired
    UsersDao usersDao;
    /**
    * 新增
    */

    @Override
    public int saveUsers(Users users) {
    int result = usersDao.saveUsers(users);

    return result ;
    }

    /**
    * 查询
    *
    */


    @Override
    public int findUsers(Users users) {

    Map<String,Object> params = new HashMap<>();
    params.put("userName",users.getUserName());
    params.put("password", users.getPassword());
    Users user = usersDao.findUsers(params);

    if(null != user){
    return 1;
    }else{
    return 0;
    }
    }
    }
    3.3 impl下的GetToken
    package com.yiyezhiqiu.jwt.jwt.service.impl;

    import com.auth0.jwt.JWT;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.yiyezhiqiu.jwt.jwt.domain.Users;
    import org.springframework.context.annotation.Bean;
    import org.springframework.stereotype.Component;

    /**
    * 生成token
    */
    @Component("GetToken")
    public class GetToken {

    public String token(Users users){

    String token = "";
    token = JWT.create().withAudience(users.getUserName()).sign(Algorithm.HMAC256(users.getPassword()));

    return token;
    }
    }

    4.dao层
    package com.yiyezhiqiu.jwt.jwt.dao;

    import com.yiyezhiqiu.jwt.jwt.domain.Users;
    import org.apache.ibatis.annotations.Mapper;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Repository;

    import java.util.Map;

    @Mapper
    @Repository
    public interface UsersDao {

    /**
    * 注册用户
    */

    public int saveUsers(Users users);

    /**
    * 查询用户
    */

    public Users findUsers (Map<String,Object> params);

    }

    5.configure
    package com.yiyezhiqiu.jwt.jwt.configure;

    import com.yiyezhiqiu.jwt.jwt.interceptor.MyInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

    @Configuration
    public class MyWebMvcConfigure implements WebMvcConfigurer {

    /**
    * 拦截url并给相应拦截处理器处理
    * @param registry
    */

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

    registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**")//拦截所有
    .excludePathPatterns("/users/register");//不拦截这个注册路径
    }

    }

    6.interceptor

    package com.yiyezhiqiu.jwt.jwt.interceptor;

    import com.alibaba.fastjson.JSONObject;
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.yiyezhiqiu.jwt.jwt.annotation.LoginAnnotation;
    import com.yiyezhiqiu.jwt.jwt.annotation.OtherPermit;
    import com.yiyezhiqiu.jwt.jwt.dao.UsersDao;
    import com.yiyezhiqiu.jwt.jwt.domain.Users;
    import com.yiyezhiqiu.jwt.jwt.service.IUsersService;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;

    import javax.annotation.PostConstruct;
    import javax.annotation.Resource;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.PrintWriter;
    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.Map;

    @Slf4j
    @Component
    public class MyInterceptor implements HandlerInterceptor {


    @Autowired
    IUsersService usersService;

    @Autowired
    UsersDao usersDao;
    private static MyInterceptor myInterceptor;

    /**
    * 这一段用来解决依赖注入不成功问题
    */
    @PostConstruct
    public void init (){
    myInterceptor = this;
    myInterceptor.usersDao = this.usersDao;
    }


    /**
    * springMVC正常流程时,处理器处理controller前被拦截处理
    * @param request
    * @param response
    * @param handler
    * @return
    * @throws Exception
    */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    JSONObject jsonObject = new JSONObject();
    String token = request.getHeader("token");
    //HandleMethod包含一些controller的方法,handler 就是一个全路径方法
    HandlerMethod handlerMethod = (HandlerMethod)handler;
    Method method = handlerMethod.getMethod();
    //思路,通过判断请求的路径中的方法是否有相应的注解
    if(method.isAnnotationPresent(LoginAnnotation.class)){
    log.info("这是登陆");
    return true;
    }

    //需要验证token
    if(method.isAnnotationPresent(OtherPermit.class)){
    //重置reset
    response.reset();
    //设置编码格式
    response.setCharacterEncoding("utf-8");
    response.setContentType("application/json");
    //这里用reponse.getWriter()后面会报重复使用的错
    ServletOutputStream pw = response.getOutputStream();

    log.info("进来验证token");
    if(StringUtils.isEmpty(token)){
    jsonObject.put("message","no token");

    pw.print(jsonObject.toJSONString());
    return false;
    }else{
    try{
    String userName = JWT.decode(token).getAudience().get(0);
    log.info("userName;"+userName);
    Map<String,Object> map = new HashMap<>();
    map.put("userName",userName);
    log.info("userDao:"+usersDao);
    log.info("userservice:"+usersService);
    Users users = myInterceptor.usersDao.findUsers(map);

    try{
    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(users.getPassword())).build();
    jwtVerifier.verify(token);
    return true;
    }catch (Exception e){
    jsonObject.put("message","token invalid");
    jsonObject.put("code","401");
    pw.print(jsonObject.toJSONString());
    return false;
    }

    }catch(Exception e){
    jsonObject.put("message","token invalid");
    jsonObject.put("code","401");
    pw.print(jsonObject.toJSONString());
    return false;
    }


    }

    }
    return false;
    }


    /**
    * MVC时处理器处理controller后被拦截处理
    * @param request
    * @param response
    * @param handler
    * @param modelAndView
    * @throws Exception
    */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }


    /**
    * 在返回视图前拦截
    * @param request
    * @param response
    * @param handler
    * @param ex
    * @throws Exception
    */

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
    }

    7.annotation;
      7.1 LoginAnnotation
      
    package com.yiyezhiqiu.jwt.jwt.annotation;

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;

    /**
    * 注明是登陆注解
    */

    @Target({ElementType.METHOD,ElementType.TYPE}) //注解放在哪,方法上还是类还是哪里
    @Retention(RetentionPolicy.RUNTIME)//啥时候启用,运行时
    public @interface LoginAnnotation {

    boolean get() default true;

    }

    7.2 Otherpermit
      
    package com.yiyezhiqiu.jwt.jwt.annotation;

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;

    /**
    * 其他页面注解
    */
    @Target({ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface OtherPermit {

    boolean other() default true;
    }


    8.domain
    package com.yiyezhiqiu.jwt.jwt.domain;

    import lombok.Data;

    @Data
    public class Users {

    private int id;
    private String userName;
    private String password;
    private String gender;

    }
    9.UsersMapping.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.yiyezhiqiu.jwt.jwt.dao.UsersDao">

    <insert id = "saveUsers" parameterType="com.yiyezhiqiu.jwt.jwt.domain.Users" keyProperty="id" useGeneratedKeys="true">
    insert into users(user_name,password,gender) values (#{userName},#{password},#{gender})
    </insert>

    <select id="findUsers" parameterType="java.util.HashMap" resultType="com.yiyezhiqiu.jwt.jwt.domain.Users">

    select * from users where
    user_name = #{userName}
    <if test="password != null and password != ''">
    and password = #{password}
    </if>

    </select>
    </mapper>
    10. application.yml

    #端口号
    server:
    port: 8088


    #数据库
    spring:
    datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
    username: root
    password: zhang


    #dao和xml映射
    mybatis:
    mapper-locations: classpath:mapper/*.xml
    type-aliases-package: com.yiyezhiqiu.jwt.jwt.domain


    #可以打印出sql语句
    logging:
    level:
    com:
    yiyezhiqiu:
    jwt:
    jwt:
    dao: debug

    11.pom.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yiyezhiqiu.jwt</groupId>
    <artifactId>jwt</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>jwt</name>
    <description>Demo project for Spring Boot</description>

    <properties>
    <java.version>1.8</java.version>
    </properties>

    <dependencies>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.1</version>
    </dependency>
    <!--jwt 依赖-->
    <dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
    </dependency>

    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.54</version>
    </dependency>

    <dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.4.0</version>
    </dependency>

    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    </dependency>

    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>
    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
    <exclusion>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    </exclusion>
    </exclusions>
    </dependency>
    </dependencies>

    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    </plugins>
    </build>

    </project>

    结果:postman调试

    1.登陆测试:输入用户名,密码。而且为正确

    2.登陆测试,输入用户名和密码不正确


    3. 不带token,访问其他页面

     4.带正确toke访问其他页面

    
    

     5.带不正确token访问其他页面

    github地址:https://github.com/yiyeluowuchen/springboot-jwt-token.git




    总结:
    遇到问题与解决
    1.问题:在拦截器 MyInterceptor中以下注入失败,一直报空。
    @Autowired
    IUsersService usersService;

    @Autowired
    UsersDao usersDao;

    解决:
    /**
    * 这一段用来解决依赖注入不成功问题
    */
    private static MyInterceptor myInterceptor;
    @PostConstruct
    public void init (){
    myInterceptor = this;
    myInterceptor.usersDao = this.usersDao;
    }
    解决后调用方式:
    Users users = myInterceptor.usersDao.findUsers(map);

    解决该问题用到博客:
    https://blog.csdn.net/georgeshaw1/article/details/74943089

    2.
    问题:在response.getWriter()时,报getWriter()has already been called for this response 异常
    解决:
      分析:该异常是response异常被其他调用了,我这里主要是因为在controller中有返回值给前端,然后在这里MyInterceptor中又用,就会导致这种情况
       解决办法:
        使用 ServletOutputStream pw = response.getOutputStream();代替

    3.
    报有:
    ava.io.CharConversionException: Not an ISO 8859-1 character: [失]

    分析:这是因为使用getOutputStrieam不能输出中文字符,改成英文就好了


    4.多学习下注解的声明和使用场景

  • 相关阅读:
    LINX中的各种alloc
    Enea LINX代码分析之二(ECM_RX)
    Enea LINX代码分析之一
    看代码和写代码还是很不同的
    sctp bind
    sockaddr和sockaddr_in
    pthread条件变量
    System V IPV & Posix IPC(摘自Unix网络编程卷2)
    [宽度优先搜索] FZU-2150 Fire Game
    [字符哈希] POJ 3094 Quicksum
  • 原文地址:https://www.cnblogs.com/yiyezhiqiuwuchen/p/11991986.html
Copyright © 2011-2022 走看看