JWT生成Token示例

该博客详细介绍了如何在SpringBoot项目中集成JWT来生成Token,包括创建项目、添加依赖、配置SwaggerUI、application.properties设置、Redis配置、JWT Token生成类的编写、User实体类与密码盐加密处理,以及 Dao、Service、ServiceImpl 和 Controller 层的实现步骤。

使用JWT生成Token

1、创建springboot项目

2、添加pom依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--springboot test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>false</optional><!--依赖是否被传递 -->
        </dependency>
        <!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-redis</artifactId>
            <version>1.4.5.RELEASE</version>
        </dependency>
        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.31</version>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.1</version>
        </dependency>
        
        <!--jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.3.0</version>
        </dependency>

3、SwaggerUI配置

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.example.redis"))
                .build();
    }
    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("SpringBoot接口")
                .version("0.1")
                .description(null)
                .build();
    }
}

4、application.properties配置

#redis
spring.redis.database=0
spring.redis.host=xx.xx.xx.xx
spring.redis.port=6379
spring.redis.password=xx

spring.datasource.url=jdbc:mysql://xx/xx?useSSL=false&useUnicode=true&characterEncoding=utf8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=xx
spring.datasource.password=xx

5、redis配置


@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        return redisTemplate;
    }
}

6、JWT生成Token类

public class JwtUtil {
    //秘钥
    public static final String SECRET = "Guesswho";
    //过期时间
    public static final int EXPIRE = 5;


    /**
     * 由字符串生成加密key
     */
    public static SecretKey generateKey(String secretKey) {
        Charset charset = Charset.forName("utf-8");
        Encoder encoder = Base64.getEncoder();
        byte[] encodedKey = encoder.encode(secretKey.getBytes(charset));
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");// 根据给定的字节数组使用AES加密算法构造一个密钥,使用 encodedKey中的始于且包含 0 到前 leng 个字节。
        return key;
    }

    //生成jwt token
    public static String createToken(int userId) throws UnsupportedEncodingException {
        Calendar nowTime = Calendar.getInstance();
        nowTime.add(Calendar.HOUR, EXPIRE);
        Date expireDate = nowTime.getTime();

        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        String token = JWT.create()
                .withHeader(map)//头
                .withClaim("userId", userId)
                .withIssuedAt(new Date())//签名时间
                .withExpiresAt(expireDate)//过期时间
                .sign(Algorithm.HMAC256(SECRET));//签名
        return token;
    }

    /*
    * 验证token
    * */
    public static Map<String, Claim> verifyToken(String token) throws Exception {
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        DecodedJWT jwt = null;
        try {
            jwt = verifier.verify(token);
        } catch (Exception e) {
            throw new Exception("token过期,请重新登陆");
        }
        return jwt.getClaims();
    }

    /*
    * 解析token
    * */
    public static Map<String, Claim> parseToken(String token) {
        DecodedJWT jwt = JWT.decode(token);
        return jwt.getClaims();
    }

}

7、创建User实体类

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String username;

    private String password;

    private String salt;
}

用户的Model类

@Data
public class UserModel {
    @ApiModelProperty(value = "用户姓名",required = true,example = "hello")
    @NotBlank
    String username;

    @ApiModelProperty(value = "用户密码",required = true,example = "Guess")
    @NotBlank
    String password;
}

创建密码盐对密码加密的接受类


@Data
public class SaltAndPassword {

    private String mixedPassword;
    private String salt;

    public SaltAndPassword(String mixedPassword, String salt) {
        this.mixedPassword = mixedPassword;
        this.salt = salt;
    }
}

密码盐

public class PasswordUtil {
    /**
     * 使用指定密码盐对密码进行加密
     */
    public static String mix(String password, String salt) {
        String newPassword = DigestUtils.md5Hex(password) + salt;
        return DigestUtils.md5Hex(newPassword);
    }

    /*
    * 使用随机密码盐对密码加密
    * */
    public static SaltAndPassword mix(String password) {
        String salt = getRandomString(4);
        String mixPassword = mix(password,salt);
        return new SaltAndPassword(mixPassword,salt);
    }

    /**
     * 生成随机字符串
     */
    public static String getRandomString(int length) {
        Random random = new Random();
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int num = random.nextInt(3);
            long result = 0;
            switch (num) {
                case 0:
                    result = Math.round(Math.random() * 25 + 65);
                    stringBuffer.append(String.valueOf((char) result));
                    break;
                case 1:
                    result = Math.round(Math.random() * 25 + 97);
                    stringBuffer.append(String.valueOf((char) result));
                    break;
                case 2:
                    stringBuffer.append(String.valueOf(new Random().nextInt(10)));
                    break;
            }
        }
        return stringBuffer.toString();
    }
}

8、Dao层

public interface UserRepository extends JpaRepository<User,Integer> {

    User findUserByUsername(String username);

    User findUserById(int id);

}

9、service层

public interface UserService {
    String login(String username, String password) throws Exception;

    User register(String name,String password) throws Exception;

    User findUserById(int id);

    User validUser(String name,String password) throws Exception;

    String getTokenEntity(User user);
    
}

10、serviceImpl

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public String login(String username, String password) throws Exception {
        //验证账号和密码
        User user = validUser(username, password);
        //返回Token
        return getTokenEntity(user);
    }

    @Override
    public User register(String name, String password) throws Exception {
        User user = userRepository.findUserByUsername(name);
        SaltAndPassword saltAndPassword = PasswordUtil.mix(password);
        if (user == null) {
            user = new User();
            user.setUsername(name);
            user.setPassword(saltAndPassword.getMixedPassword());
            user.setSalt(saltAndPassword.getSalt());
            return userRepository.save(user);
        } else {
            throw new Exception("user is existed");
        }

    }

    @Override
    public User findUserById(int id) {
        return userRepository.findUserById(id);
    }

    @Override
    public User validUser(String name, String password) throws Exception {
        User user = userRepository.findUserByUsername(name);
        if (user != null) {
            String pwd = PasswordUtil.mix(password, user.getSalt());
            if (pwd.equals(user.getPassword())) {
                return user;
            } else {
                throw new Exception("password is not correct");
            }
        } else {
            throw new Exception("user is not exist");
        }
    }

    @Override
    public String getTokenEntity(User user) {
        String token = null;
        try {
            token = JwtUtil.createToken(user.getId());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return token;
    }
}

controller层

@RestController
public class UserController {
    @Autowired
    private UserService userService;

    @ApiOperation(value = "账号密码登录", httpMethod = "POST", notes = "账号密码登录")
    @PostMapping("/login")
    public Object login(@RequestBody UserModel model) throws Exception {
        HashMap<String, String> result = new HashMap<>();
        result.put("token", userService.login(model.getUsername(), model.getPassword()));
        return result;
    }

    @ApiOperation(value = "通过Token获取用户信息", httpMethod = "GET",notes ="通过Token获取用户信息" )
    @GetMapping("/getUser")
    public User getUser(String token) throws Exception {
        Map<String, Claim> map = JwtUtil.verifyToken(token);
        Claim claim = map.get("userId");
        User user = userService.findUserById(claim.asInt());
        return user;
    }

    @ApiOperation(value = "用户注册", httpMethod = "POST", notes = "用户注册")
    @PostMapping("/register")
    public User register(@RequestBody UserModel model) throws Exception {
        User user = userService.register(model.getUsername(), model.getPassword());
        return user;
    }
}

测试结果

在这里插入图片描述
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值