feign默认不携带token问题&使用 jwt 作为 token

feign 默认不携带 token,需要进行配置:

  1. 编辑 application 设置 hystrix 的隔离模式(编辑每一个需要token处理业务逻辑的服务的dev,添加如下内容)
hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE   #设置hysitrix的隔离级别为信号量,只有这个级别才可以拿到客户端发送的token,默认级别是THREAD
  1. 在当前的每一个服务中创建配置类 MyRequestInterceptor 实现 RequestInterceptor 接口
package com.zhiyou100.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;

/**feign使用的时候通过Service获取别的服务器中的数据,出现token丢失的问题,
 * 为了解决这个问题,我们创建这个配置类,并且在dev中添加配置
 * @author zhangfan
 * @date 2019/10/21
 */
@Configuration
public class MyRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {

        //获取    客户端的授权信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        //只有客户端传递token的时候才去添加
        if (authentication != null){

            //获取token详细信息
            Object details = authentication.getDetails();

            if (details instanceof OAuth2AuthenticationDetails){

                OAuth2AuthenticationDetails details1 = (OAuth2AuthenticationDetails) details;

                //获取token
                String token = details1.getTokenValue();

                //在feign的请求头中添加token
                requestTemplate.header("Authorization","bearer" + token);

            }

        }
    }
}

修改 auth 服务,从数据库读取和验证用户信息:

1. 制作数据库
    需要 3 张表:用户表,角色表和用户角色表(关系表)
DROP DATABASE IF EXISTS `spring_cloud_01`;
CREATE DATABASE `spring_cloud_01`;

USE `spring_cloud_01`;

CREATE TABLE IF NOT EXISTS `user` (
    `id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    `account` VARCHAR(20) NOT NULL COMMENT '账号',
    `password` VARCHAR(100) NOT NULL COMMENT '密码'
) COMMENT '用户表';

INSERT INTO user VALUES(NULL, 'zhangsan', '{bcrypt}$2a$10$YQjMpUJ116gDNBVKntYnJewx4/mdhLar38VBYR/5DX7mYTXw/cPcm');
INSERT INTO user VALUES(NULL, 'lisi', '{bcrypt}$2a$10$YQjMpUJ116gDNBVKntYnJewx4/mdhLar38VBYR/5DX7mYTXw/cPcm');

CREATE TABLE IF NOT EXISTS `role` (
    `id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    `name` VARCHAR(20) NOT NULL COMMENT '名称'
) COMMENT '角色表';

INSERT INTO role VALUES(NULL, 'ADMIN');
INSERT INTO role VALUES(NULL, 'EMPLOYEE');

CREATE TABLE IF NOT EXISTS `user_role` (
    `id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    `user_id` INT NOT NULL COMMENT '用户主键',
    `role_id` INT NOT NULL COMMENT '角色主键'   
) COMMENT '用户角色表';   

INSERT INTO user_role VALUES(NULL, 1, 1);
INSERT INTO user_role VALUES(NULL, 2, 2);

2. 在auth中编写 User 和 Role 实体类
    在 User 中增加 private List roles; 属性
        表示用户拥有的所有角色

前提:导入依赖

<!--lombok依赖,自动生成实体类中的get set 构造方法-->
        
            org.projectlombok
            lombok
            true
        

        <!--mysql依赖-->
        
            mysql
            mysql-connector-java
            runtime
        

        <!--MyBatis-Plus (简称 MP)是一个 MyBatis 的增强工具,
         在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。-->
        
            com.baomidou
            mybatis-plus-boot-starter
            3.2.0
        
        
            com.baomidou
            mybatis-plus
            3.2.0
        

        <!--测试依赖-->
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
3. Role 类实现 GrantedAuthority 接口
    getAuthority() 方法返回角色名字(name 属性的值)
package com.zhiyou100.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;

/**
 * @author zhangfan
 * @date 2019/10/21
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("name = role")
public class Role implements GrantedAuthority {

    @TableId(type = IdType.AUTO)
    private Integer id;

    private String name;

    //返回角色的名字
    @Override
    public String getAuthority() {
        return name;
    }
}

4. User 类实现 UserDetails 接口
    getAuthorities() 方法返回用户拥有的角色(roles 属性的值)
    getUsername() 方法返回用户账号(account 属性的值)
    getPassword() 方法返回用户密码(password 属性的值)
    isAccountNonExpired() 方法返回账号 是否  没有过期(true)
    isAccountNonLocked() 方法返回账号 是否 没有被锁定(true)
    isCredentialsNonExpired() 方法返回账号 是否 没有过期(true)
    isEnabled() 方法返回账号 是否 启用(true)
package com.zhiyou100.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;

/**
 * @author zhangfan
 * @date 2019/10/21
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User implements UserDetails {

    @TableId(type = IdType.AUTO)
    private Integer id;

    private String account;

    private String password;

    //在user中增加属性,表示用户拥有的所有角色
    private List<Role> roles;

    //返回用户拥有的角色
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles;
    }

    //返回用户账号
    @Override
    public String getUsername() {
        return account;
    }

    //getPassword()方法被Date注解吃了,就不用我们返回了

    //返回账号是否没有过期:是true
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    //方法返回账号是否没有被锁定 是 true
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    //方法返回账号是否没有过期 是
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    //方法返回账号  是否启用
    @Override
    public boolean isEnabled() {
        return true;
    }
}

5. 创建并实现 UserDao 接口(auth)
    User findByAccount(String account);
package com.zhiyou100.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhiyou100.entity.User;

/**
 * @author zhangfan
 * @date 2019/10/21
 */
public interface UserDao extends BaseMapper<User> {

    /**
     * 根据账号查询用户信息(包括用户的角色信息)
     * @param account   账号
     * @return  用户信息
     */
    User findByAccount(String account);
}

mapper例子

<?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" >
>

    >
        >>
        >>
        >>
        >
            >>
            >>
        >
    >