springoboot与springsecurity整合中级篇

根据上一章https://blog.csdn.net/he_lei/article/details/115482297继续扩展,jwt来前后分离
引入pom

 <!--生成token-->
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.2.0</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.7.0</version>
    </dependency>

首先要用到jwt生成工具


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.*;

/**
 * @description: 描述
 * @create: 2019-07-22 11:26
 */
public class JwtUtil {


    /**
     * token 过期时间, 单位: 秒. 这个值表示 30 天
     */
    private static final long TOKEN_EXPIRED_TIME = 30 * 24 * 60 * 60;

    /**
     * jwt 加密解密密钥, 这里请自行赋值,本人暂且使用随机数16位
     */
    private static final String JWT_SECRET = "1AsdadSAS123daXX";

    public static final String jwtId = "tokenId";

    /**
     * 创建JWT
     *
     * @param claims 这个是payLoad的部分内容, jwt格式:jwtHeader.jwtPayLoad.Signature
     */
    public static String createJWT(Map<String, Object> claims, Long time) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
        Date now = new Date(System.currentTimeMillis());

        SecretKey secretKey = generalKey();
        long nowMillis = System.currentTimeMillis();//生成JWT的时间
        //下面就是在为payload添加各种标准声明和私有声明了
        JwtBuilder builder = Jwts.builder().setClaims(claims) //这里其实就是new一个JwtBuilder,设置jwt的body
                .setClaims(claims)          //如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setHeaderParam("alg", "HS256")  //设置header
                .signWith(signatureAlgorithm, secretKey);//设置签名使用的签名算法和签名使用的秘钥
        if (time >= 0) {
            long expMillis = nowMillis + time * 1000;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp);     //设置过期时间
        }
        return builder.compact();
    }

    /**
     * 验证jwt
     */
    public static Claims verifyJwt(String token) {
        //签名秘钥,和生成的签名的秘钥一模一样
        SecretKey key = generalKey();
        Claims claims;
        try {
            claims = Jwts.parser()  //得到DefaultJwtParser
                    .setSigningKey(key)         //设置签名的秘钥
                    .parseClaimsJws(token).getBody();
        } catch (Exception e) {
            claims = null;
        }//设置需要解析的jwt
        return claims;
    }


    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public static SecretKey generalKey() {
        String stringKey = JWT_SECRET;
        byte[] encodedKey = Base64.decodeBase64(stringKey);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "HS256");
        return key;
    }

    /**
     * 根据userId和openid生成token
     */
    public static String generateToken(String id) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);
        map.put("role","a");
        return createJWT(map, TOKEN_EXPIRED_TIME);
    }

    public static String GetgenerateToken(String token) {
        return verifyJwt(token).get("id").toString();
    }
    public static String generateToken(SecurityUserEntity extendUserBean, String name, String authorities) {
        Map<String, Object> map = new HashMap<>();
        map.put("id",extendUserBean.getId());
        map.put("user",extendUserBean);
        map.put("name", name);
        map.put("role",authorities);
        return createJWT(map, TOKEN_EXPIRED_TIME);
    }

}

继承OncePerRequestFilter 重写doFilterInternal

package com.helei.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.helei.commons.Resp;
import com.helei.entity.SecurityUserEntity;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Slf4j
@Component
public class JWTAuthenticationFilter extends OncePerRequestFilter {


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String header = request.getHeader("head");
       /* if(StringUtils.isBlank(header)){
            header = request.getParameter(SecurityConstant.HEADER);
        }*/
        Boolean notValid = StringUtils.isBlank(header);
        if (notValid) {
            chain.doFilter(request, response);
            return;
        }
        try {
            // UsernamePasswordAuthenticationToken 继承 AbstractAuthenticationToken 实现 Authentication
            //  所以当在页面中输入用户名和密码之后首先会进入到 UsernamePasswordAuthenticationToken验证(Authentication),
            UsernamePasswordAuthenticationToken authentication = getAuthentication(header, response);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception e) {
            e.toString();
        }

        chain.doFilter(request, response);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(String header, HttpServletResponse response) {

        //  用户名
        String username = null;
        // 权限
        //  List<GrantedAuthority> authorities = new ArrayList<>();

        Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
        SecurityUserEntity extendUserBean1 = null;
        try {
            //  解析token
            Claims claims = JwtUtil.verifyJwt(header);
            logger.info("claims:" + claims);
            //   获取用户名
            username = claims.get("name").toString();
            logger.info("name:" + username);
            // 获取权限
            String[] roles = claims.get("role").toString().split(",");
            for (String s : roles) {
                authorities.add(new SimpleGrantedAuthority("ROLE_" + s));
            }
            //  if(!StringUtils.isEmpty(authority)){
            //  authorities.add(new SimpleGrantedAuthority("ROLE_a"));
            // }

        } catch (ExpiredJwtException e) {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = null;
            try {
                out = response.getWriter();
                out.write(new ObjectMapper().writeValueAsString(Resp.getNew().fail("登录已失效,请重新登录")));
            } catch (Exception jsonProcessingException) {
                jsonProcessingException.printStackTrace();
            }
            out.flush();
            out.close();
        } catch (Exception e) {
            log.error(e.toString());
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = null;
            try {
                out = response.getWriter();
                out.write(new ObjectMapper().writeValueAsString(Resp.getNew().fail("解析token错误")));
            } catch (Exception jsonProcessingException) {
                jsonProcessingException.printStackTrace();
            }
            out.flush();
            out.close();

        }
        System.out.println(new Gson().toJson(authorities));
        if (StringUtils.isNotBlank(username)) {
            //  踩坑提醒 此处password不能为null
            UserAuthentication userAuthentication = new UserAuthentication(username, "", authorities);
            userAuthentication.setExtendUserBean(extendUserBean1);
            //    User principal = new User(username, "", authorities);
            return new UsernamePasswordAuthenticationToken(userAuthentication, null, authorities);
        }
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值