前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前后端分离配置token

前后端分离配置token

作者头像
用户5899361
发布2020-12-07 15:37:10
7500
发布2020-12-07 15:37:10
举报
文章被收录于专栏:学习java的小白

解决ajax跨域请求:

代码语言:javascript
复制
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
        corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
        corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法

        return corsConfiguration;
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
        return new CorsFilter(source);
    }

}

JSON工具类:

代码语言:javascript
复制
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

/**
 * @ProjectName: LieIdle
 * @Package: com.utils
 * @Author: huat
 * @Date: 2020/4/8 16:57
 * @Version: 1.0
 */
@Slf4j
public class JsonUtil {
    public static final ObjectMapper objectMapper=new ObjectMapper();

    /**
     * 将对象转为json
     * @param object  对象
     * @return json
     */
    public static String ObjectToString(Object object) {
        if(null==object){
            return null;
        }
        if(object.getClass()==String.class){
            return (String)object;
        }
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            log.info(object+"序列化出错"+e.getMessage());
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将json转换成对象
     * @param json json字符串
     * @param tClass 类
     * @param <T> 泛型
     * @return 返回对象
     */
    public static <T> T toBean(String json,Class<T> tClass){
        try {
            return objectMapper.readValue(json,tClass);
        } catch (IOException e) {
            log.info(json+"转对象失败"+e.getMessage());
            e.printStackTrace();
            return null;
        }
    }


}

JWT工具类:

代码语言:javascript
复制
package cn.bdqn.token;


import cn.bdqn.entity.Payload;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.joda.time.DateTime;

import javax.servlet.http.HttpServletRequest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

/**
 * @ProjectName: LieIdle
 * @Package: com.utils
 * @Author: huat
 * @Date: 2020/4/8 16:22
 * @Version: 1.0
 */
public class JwtUtil {
    private final static String JWT_PAYLOAD_USER_KEY = "user";

    /**
     * 私钥加密token
     *
     * @param userInfo   载荷中的数据
     * @param privateKey 私钥
     * @param expire     过期时间  单位分钟
     * @return
     */
    public static String generateTokenExpireInMinutes(Object userInfo, PrivateKey privateKey, int expire) {
        return Jwts.builder()
                .claim(JWT_PAYLOAD_USER_KEY, JsonUtil.ObjectToString(userInfo))
                .setId(createJTI())
                .setExpiration(DateTime.now().plusMinutes(expire).toDate())
                .signWith(privateKey, SignatureAlgorithm.RS256)
                .compact();
    }
    /**
     * 私钥加密token
     *
     * @param userInfo   载荷中的数据
     * @param privateKey 私钥
     * @param expire     过期时间  单位秒
     * @return
     */
    public static String generateTokenExpireInSeconds(Object userInfo, PrivateKey privateKey, int expire) {
        return Jwts.builder()
                .claim(JWT_PAYLOAD_USER_KEY, JsonUtil.ObjectToString(userInfo))
                .setId(createJTI())
                .setExpiration(DateTime.now().plusSeconds(expire).toDate())
                .signWith(privateKey, SignatureAlgorithm.RS256)
                .compact();
    }

    private static String createJTI() {
        return new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes()));
    }

    /**
     * 公钥解析token
     * @param token 用户请求的令牌
     * @param publicKey 公钥
     * @return
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey){
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }
    /**
     * 获取token中的载荷信息
     * @param token 用户请求的令牌
     * @param publicKey 公钥
     * @param userType  用户类型
     * @param <T>
     * @return  用户信息
     */
    public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey, Class<T> userType) {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        Payload<T> payload = new Payload<T>();
        payload.setId(body.getId());
        payload.setUserInfo(JsonUtil.toBean(body.get(JWT_PAYLOAD_USER_KEY).toString(),userType));
        payload.setExpiration(body.getExpiration());
        return payload;
    }
    /**
     * 获取token中的载荷信息
     * @param token 用户请求的令牌
     * @param publicKey 公钥
     * @param <T>
     * @return  用户信息
     */
    public static <T> Payload<T> getInfoFromToken(String token, PublicKey publicKey) {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        Payload<T> payload = new Payload<T>();
        payload.setId(body.getId());
        payload.setExpiration(body.getExpiration());
        return payload;
    }


}

生成公钥私钥工具类:

代码语言:javascript
复制
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;

/**
 * @ProjectName: LieIdle
 * @Package: com.utils
 * @Author: huat
 * @Date: 2020/4/8 17:09
 * @Version: 1.0
 */
@Configuration
@ConfigurationProperties("rsa.key")//从配置文件中获取头信息是rsa.key的配置
public class RsaKeyProperties {
    private String publicKeyFile;
    private String privateKeyFile;
    private PublicKey publicKey;
    private PrivateKey privateKey;
    @PostConstruct//在初始化完成之后执行此方法
    public void createRsaKey() throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
        publicKey=RsaUtil.getPublicKey(publicKeyFile);
        privateKey=RsaUtil.getPrivateKey(privateKeyFile);
    }

    public String getPublicKeyFile() {
        return publicKeyFile;
    }

    public void setPublicKeyFile(String publicKeyFile) {
        this.publicKeyFile = publicKeyFile;
    }

    public String getPrivateKeyFile() {
        return privateKeyFile;
    }

    public PublicKey getPublicKey() {
        return publicKey;
    }

    public void setPublicKey(PublicKey publicKey) {
        this.publicKey = publicKey;
    }

    public PrivateKey getPrivateKey() {
        return privateKey;
    }

    public void setPrivateKey(PrivateKey privateKey) {
        this.privateKey = privateKey;
    }

    public void setPrivateKeyFile(String privateKeyFile) {
        this.privateKeyFile = privateKeyFile;
    }
}

RSA加密方式:

代码语言:javascript
复制
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * @ProjectName: LieIdle
 * @Package: com.utils
 * @Author: huat
 * @Date: 2020/4/8 17:09
 * @Version: 1.0
 */

public class RsaUtil {
    private final static int DEFAULT_KEY_SIZE=2048;
    /**
     * 根据密文,生成rea公钥和私钥,并写入指定文件
     * @param publicKeyFileName 公钥文件路径
     * @param privateKeyFileName 私钥文件路径
     * @param secret 盐
     * @param keySize 大小
     */
    public static void generateKey(String publicKeyFileName,String privateKeyFileName,String secret, int keySize) throws NoSuchAlgorithmException, IOException {
        KeyPairGenerator keyPairGenerator= KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom=new SecureRandom(secret.getBytes());
        keyPairGenerator.initialize(Math.max(keySize,DEFAULT_KEY_SIZE),secureRandom);
        KeyPair keyPair=keyPairGenerator.genKeyPair();
        //获取公钥并写出
        byte[] publicKeyByte=keyPair.getPublic().getEncoded();
        publicKeyByte= Base64.getEncoder().encode(publicKeyByte);
        writeFile(publicKeyFileName,publicKeyByte);
        //获取公钥并写入
        byte[] privateKeyByte=keyPair.getPrivate().getEncoded();
        privateKeyByte= Base64.getEncoder().encode(privateKeyByte);
        writeFile(privateKeyFileName,privateKeyByte);
    }

    /**
     * 获取秘钥
     * @param bytes 秘钥的字节形式
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private static PrivateKey getPrivateKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        bytes=Base64.getDecoder().decode(bytes);
        PKCS8EncodedKeySpec spec=new PKCS8EncodedKeySpec(bytes);
        KeyFactory keyFactory=KeyFactory.getInstance("RSA");
        return keyFactory.generatePrivate(spec);
    }
    /**
     * 获取公钥
     * @param bytes 公钥的字节形式
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     */
    private static PublicKey getPublicKey(byte[] bytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
        bytes=Base64.getDecoder().decode(bytes);
        X509EncodedKeySpec spec=new X509EncodedKeySpec(bytes);
        KeyFactory keyFactory=KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(spec);
    }

    /**
     * 从文件中读取公钥
     * @param fileName 公钥保存路径 相对于classpath
     * @return 公钥对象
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    public static PublicKey getPublicKey(String fileName) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
        byte[] bytes=readFile(fileName);
        return getPublicKey(bytes);
    }
    /**
     * 从文件中读取公钥
     * @param fileName 公钥保存路径 相对于classpath
     * @return 私钥对象
     * @throws InvalidKeySpecException
     * @throws NoSuchAlgorithmException
     */
    public static PrivateKey getPrivateKey(String fileName) throws InvalidKeySpecException, NoSuchAlgorithmException, IOException {
        byte[] bytes=readFile(fileName);
        return getPrivateKey(bytes);
    }
    private static byte[] readFile(String fileName) throws IOException {
        return Files.readAllBytes(new File(fileName).toPath());
    }
    private static void writeFile(String fileName,byte[] bytes) throws IOException {
        File file=new File(fileName);
        if(!file.exists()){
            file.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream( fileName);
        fos.write(bytes);
        fos.close();

    }

    public static void main(String[] args) {
        try {
            generateKey("E:\\桌面\\public.pub","E:\\桌面\\private","jinzhending,@,",2048);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

登陆:

代码语言:javascript
复制
import cn.bdqn.entity.User;
import cn.bdqn.service.UserService;
import cn.bdqn.token.JwtUtil;
import cn.bdqn.token.RsaKeyProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: Student
 * @Package: com.controller
 * @Author: huat
 * @Date: 2020/5/11 14:54
 * @Version: 1.0
 */
@RestController
public class LoginController {
    @Autowired
    UserService userService;
    @Autowired
    RsaKeyProperties rsaKeyProperties;
    /**
     * 登陆
     * @param username 账号
     * @param password  密码
     * @return
     */
    @PostMapping("login")
    public Map<String,Object> login(String username, String password, HttpServletResponse response){
        Map<String,Object> map=new HashMap<String,Object>();
      User user= userService.getUser(username, password);
      if(null!=user){

          map.put("code",200);
          map.put("msg","登陆成功");
          map.put("data","");
          String token= JwtUtil.generateTokenExpireInMinutes(user,rsaKeyProperties.getPrivateKey(),24*60);
          //必须有这句话否则前台获取不到token
          response.setHeader("Access-Control-Expose-Headers", "Authorization");

          response.setHeader("Authorization","bearer "+token);
      }else{
          map.put("code",500);
          map.put("msg","账号密码错误");
          map.put("data","");
      }
        return map;
    }
}

拦截器判断有没有登陆:

代码语言:javascript
复制
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ProjectName: Student
 * @Package: com.filter
 * @Author: huat
 * @Date: 2020/5/11 15:31
 * @Version: 1.0
 */
@Component
public class LoginInterceptor  implements HandlerInterceptor {
    /**
     * 预处理回调方法,实现处理器的预处理
     * 返回值:true表示继续流程;false表示流程中断,不会继续调用其他的拦截器或处理器
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String header = request.getHeader("Authorization");
        if(null==header){
            Map<String,Object> map=new HashMap<String,Object>();
            map.put("code",403);
            map.put("data","");
            map.put("msg","请重新登陆");
            response.setCharacterEncoding("UTF-8");
            PrintWriter writer = response.getWriter();
            writer.print(map);
            writer.flush();
            writer.close();
            return false;
        }
        return true;
    }

    /**
     * 后处理回调方法,实现处理器(controller)的后处理,但在渲染视图之前
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {


    }
    /**
     * 整个请求处理完毕回调方法,即在视图渲染完毕时回调,
     * 如性能监控中我们可以在此记录结束时间并输出消耗时间,
     * 还可以进行一些资源清理,类似于try-catch-finally中的finally,
     * 但仅调用处理器执行链中
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

    }

}

注册拦截器:

代码语言:javascript
复制
import cn.bdqn.utils.StaticUrl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @ProjectName: Document
 * @Package: com.util
 * @Author: huat
 * @Date: 2019/7/26 10:18
 * @Version: 1.0
 */


@Configuration
public class WebConfigurer implements WebMvcConfigurer {
    @Autowired
    LoginInterceptor loginInterceptor;


    // 这个方法是用来配置静态资源的,比如html,js,css,等等
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

     

    }

    // 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // addPathPatterns("/**") 表示拦截所有的请求,
        //excludePathPatterns("/login", "/register"); 表示除了登陆与注册之外,因为登陆注册不需要登陆也可以访问
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
        //super.addInterceptors(registry);    //较新Spring Boot的版本中这里可以直接去掉,否则会报错

    }


}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 解决ajax跨域请求:
  • JSON工具类:
  • JWT工具类:
  • 生成公钥私钥工具类:
  • RSA加密方式:
  • 登陆:
  • 拦截器判断有没有登陆:
  • 注册拦截器:
相关产品与服务
应用性能监控
应用性能监控(Application Performance Management,APM)是一款应用性能管理平台,基于实时多语言应用探针全量采集技术,为您提供分布式性能分析和故障自检能力。APM 协助您在复杂的业务系统里快速定位性能问题,降低 MTTR(平均故障恢复时间),实时了解并追踪应用性能,提升用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档