Cors跨域和Jwt(Token)

本文介绍了浏览器的同源策略,跨域问题的后端处理方法(如Nginx和CORS),以及如何在Java项目中使用JWTToken和编写Cors过滤器进行身份验证。详细讲解了如何在用户登录时生成Token并在请求中验证,确保安全的跨域通信。
摘要由CSDN通过智能技术生成

目录

一,浏览器的同源策略

1,同源与跨域

2,浏览器的同源策略

二,跨域处理方案(后端)

三,Cors过滤器

实现方法:①:实现Filter接口②:重写init,dofilter,destroy。③:dofilter中设置跨域配置

四,Jwt(Token)

Token的使用:Maven项目

1,导入依赖(版本自己选择)

2,编写工具类

3,用户登录的时候创建Token,放在响应头中。(使用原生的servletResponse)

4,写一个过滤器判断请求中是否存在token存在则对Token进行校验。成功则放行,不成功则返回失败。


一,浏览器的同源策略

1,同源与跨域

        url:  通讯协议://IP地址:端口号/资源路径
        两次请求的协议,ip,端口号都相同,我们认为两次请求的同源的
        否则,不同源,需要跨域(Cors)。

2,浏览器的同源策略

        浏览器发送请求,同源可以发送,不同源不能发送请求。(浏览器的安全机制)
        部分html标签支持跨域script,,a,link,img等

        但在项目中使用Ajax调用接口,默认是不能跨域的。
报错图片:

二,跨域处理方案(后端)

1,使用nginx服务器

2,Cors跨域资源共享,后端设置可以跨域。

三,Cors过滤器

跨域请求时复杂请求。
复杂请求跨域访问,会先发一次预检请求,请求方式时OPTIONS。
如果预检请求允许,发送真正的请求,不允许则控制台报错。

实现方法:
①:实现Filter接口
②:重写init,dofilter,destroy。
③:dofilter中设置跨域配置
 
HttpServletResponse  resp=(HttpServletResponse)servletResponse;
        HttpServletRequest  req=(HttpServletRequest)servletRequest;

        //设置cors:允许跨域访问

//        预检请求方式是:OPTIONS

//        1\允许哪些域可以访问我
        resp.setHeader("Access-Control-Allow-Origin","*");
//        resp.setHeader("Access-Control-Allow-Origin","http://localhost:8080");
//        resp.setHeader("Access-Control-Allow-Origin",req.getHeader("Origin"));

//        2、允许哪些请求方式
        resp.setHeader("Access-Control-Allow-Methods","get,post,OPTIONS");

//        3、请求头中包含
        resp.setHeader("Access-Control-Allow-Headers","token");

//        4、跨域是否允许携带cookie
        resp.setHeader("Access-Control-Allow-Credentials","true");

//        5、预检请求的时间间隔
        resp.setHeader("Access-Control-Max-Age","3600");

//        6、 可以向客户端浏览器暴露哪些请求头
        resp.setHeader("Access-Control-Expose-Headers", "token");

//        将请求交给目标资源
        filterChain.doFilter(req, resp);

跨域不能携带cookie和session会话跟踪。所以使用token。

四,Jwt(Token)

网址:https://jwt.io/

介绍:JWT就是一个带有用户信息的加密字符串。JWT可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。通常用于用户登录。

Jwt组成:Header(头部),Payload(载荷),Signature(签名)三部分组成,中间以点分隔。

 类库:进入官方-----libraries----Filterby(选择Java)-----自己选择下载

Token的使用:Maven项目
1,导入依赖(版本自己选择)
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.11.0</version>
</dependency>

2,编写工具类
/**
 * 用于生成和解析JWT
 */
public class JWTUtils {

    /**
     * 声明一个秘钥
     */
    private static final String SECRET = "leige";


    /**
     * 生成JWT
     *
     * @param userId   用户编号
     * @param username 用户名
     * @param auth     用户权限
     */
    public String createToken(Integer userId, String username, List<String> auth) {
        //得到当前的系统时间
        Date currentDate = new Date();
        //根据当前时间计算出过期时间 定死为5分钟
        Date expTime = new Date(currentDate.getTime() + (1000 * 60 * 5));
        //组装头数据
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");
        return JWT.create()
                .withHeader(header) //头
                .withClaim("userId", userId) //自定义数据
                .withClaim("username", username) //自定义数据
                .withClaim("auth", auth) //自定义数据
                .withIssuedAt(currentDate) //创建时间
                .withExpiresAt(expTime)//过期时间
                .sign(Algorithm.HMAC256(SECRET));
    }

    /**
     * 验证JWT并解析
     *
     * @param token 要验证的jwt的字符串
     */
    public static Boolean verifyToken(String token) {
        try{
            // 使用秘钥创建一个解析对象
            JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(SECRET)).build();
            //验证JWT
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            return true;
        }catch (TokenExpiredException e){
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 获取JWT里面相前的用户编号
     */
    public Integer getUserId(String token){
        try{
            // 使用秘钥创建一个解析对象
            JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(SECRET)).build();
            //验证JWT
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            Claim userId = decodedJWT.getClaim("userId");
            return userId.asInt();
        }catch (TokenExpiredException e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取JWT里面相前的用户名
     */
    public static String getUsername(String token){
        try{
            // 使用秘钥创建一个解析对象
            JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(SECRET)).build();
            //验证JWT
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            Claim username = decodedJWT.getClaim("username");
            return username.asString();
        }catch (TokenExpiredException e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 获取JWT里面相前权限
     */
    public List<String> getAuth(String token){
        try{
            // 使用秘钥创建一个解析对象
            JWTVerifier jwtVerifier=JWT.require(Algorithm.HMAC256(SECRET)).build();
            //验证JWT
            DecodedJWT decodedJWT = jwtVerifier.verify(token);
            Claim auth = decodedJWT.getClaim("auth");
            return auth.asList(String.class);
        }catch (TokenExpiredException e){
            e.printStackTrace();
        }
        return null;
    }

}
3,用户登录的时候创建Token,放在响应头中。(使用原生的servletResponse)
@RequestMapping("/login")
    public R loginUsers(String uname, String upassword, HttpServletResponse resp) throws UnsupportedEncodingException {
        Users user = service.Userlogin(uname);
        if (!user.getUname().equals(uname)){
            return R.loginfail();
        }else if(!user.getUpassword().equals(upassword)){
            return R.fali("用户密码错误,请重新输入");
        }else {
            String token = TokenUtil.toToken();
            //响应token
            resp.setHeader("token",token);
            return R.sussce("登录成功");
        }
    }

4,写一个过滤器判断请求中是否存在token
存在则对Token进行校验。成功则放行,不成功则返回失败。
//        获取请求头中的token
        String token = req.getHeader("token");
//        token为空或校验失败
        if (token==null || !TokenUtil.validateJWT(token)){
//            没有登录
            PrintWriter out = resp.getWriter();
            ObjectMapper mapper = new ObjectMapper();

            out.write(mapper.writeValueAsString(R.loginfail()));
            out.close();
        }else {
//            放行
            filterChain.doFilter(req,resp);
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值