校验Google,FaceBook,apple,登陆jwt(token)

google

token是客户端完成google登陆时传到后端的jwt

clientId 类似

2xxxxxxxxx2-a61mqdtnkhsxxxxxxxxxx5ca6l9.apps.googleusercontent.com

使用的maven

       <dependency>
            <groupId>com.google.api-client</groupId>
            <artifactId>google-api-client</artifactId>
            <version>1.24.1</version>
            <scope>compile</scope>
        </dependency>
 public static Boolean googleJwtVerification(String token, String clientId) {
        GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(
                new NetHttpTransport(), JacksonFactory.getDefaultInstance())
                .setAudience(Collections.singletonList(clientId)).build();
        GoogleIdToken idToken = null;
        try {
            idToken = verifier.verify(token);
            log.info("google验证解析出来的结果{}", idToken.getPayload());
            return true;
        } catch (GeneralSecurityException e) {
            log.info("验证时出现GeneralSecurityException异常");
        } catch (IOException e) {
            System.out.println("验证时出现IOException异常");
        }
        return false;
    }

facebook

需要先请求获取facebook的jwts json数据,然后转成RSAPublicKey,然后使用公钥对jwt进行验证

这里还可以加一步进行判断对clientId的验证

注意:正常facebook是不进行这一步的,因为ios同事看错了文档

因为接的下面一个,所以就会传入一个jwt过来,如果不校验的话,别人可以串改jwt然后可以生成n个新用户 。

如果是接上面那个,是可以调用接口去获取facebook用户信息的

 facebook jwt文档解释https://developers.facebook.com/docs/facebook-login/limited-login/token/validating

maven

<dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.15.0</version>
        </dependency>
        <dependency>
            <groupId>org.bitbucket.b_c</groupId>
            <artifactId>jose4j</artifactId>
            <version>0.6.4</version>
        </dependency>
 private static List<RSAPublicKey> faceBookPublicKeys = new ArrayList<>();

 private static String faceBooKJwksUrl = "https://www.facebook.com/.well-known/oauth/openid/jwks/";

public static Boolean faceBookJwtVerification(String token) {

        if (CollectionUtil.isEmpty(faceBookPublicKeys)) {
            init();
        }

        for (RSAPublicKey faceBookPublicKey : faceBookPublicKeys) {

            //根据密钥对生成RS256算法对象
            Algorithm algorithm = Algorithm.RSA256(faceBookPublicKey);

            log.info("PublicKey: " + faceBookPublicKey.getPublicExponent());

            //解密时,使用gong钥生成算法对象
            JWTVerifier verifier = JWT.require(algorithm)
                    .build();

            try {
                //验证Token,verifier自动验证
                DecodedJWT jwt = verifier.verify(token);
                log.info("验证解析出来的facebook信息:{}", jwt.getPayload());
                return true;
            } catch (JWTVerificationException e) {
                log.error("Token无法通过验证! " + e.getMessage());
                return false;
            }

        }
        return false;
    }


private static void init() {
        ReentrantLock lock = new ReentrantLock();
        lock.lock();
        try {
            if (CollectionUtil.isNotEmpty(faceBookPublicKeys)) {
                return;
            }
            log.info("查询facebook公钥开始");
            String responseResult = HttpRequest.get(faceBooKJwksUrl).setConnectionTimeout(3000).timeout(3000).execute().body();
            if (StrUtil.isNotBlank(responseResult)) {
                JSONObject jsonObject = JSONObject.parseObject(responseResult);
                JSONArray keys = jsonObject.getJSONArray("keys");
                for (int i = 0; i < keys.size(); i++) {
                    JSONObject key = keys.getJSONObject(i);
                    RsaJsonWebKey pub = null;
                    try {
                        pub = new RsaJsonWebKey(key);
                    } catch (JoseException e) {
                        e.printStackTrace();
                    }
                    //获取公钥
                    RSAPublicKey rsaPublicKey = pub.getRsaPublicKey();
                    faceBookPublicKeys.add(rsaPublicKey);
                }
            }
            log.info("查询facebook公钥结束");
        } finally {
            lock.unlock();
        }
    }

apple 

和facebook的流程差不多,就是获取到的公钥不一样,转换成RSAPublicKey 的方法也不一样

private static String appleJwksUrl = "https://appleid.apple.com/auth/keys";

private static String appleJwksCache = "{\"keys\":[{\"kty\":\"RSA\",\"kid\":\"YuyXoY\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"1JiU4l3YCeT4o0gVmxGTEK1IXR-Ghdg5Bzka12tzmtdCxU00ChH66aV-4HRBjF1t95IsaeHeDFRgmF0lJbTDTqa6_VZo2hc0zTiUAsGLacN6slePvDcR1IMucQGtPP5tGhIbU-HKabsKOFdD4VQ5PCXifjpN9R-1qOR571BxCAl4u1kUUIePAAJcBcqGRFSI_I1j_jbN3gflK_8ZNmgnPrXA0kZXzj1I7ZHgekGbZoxmDrzYm2zmja1MsE5A_JX7itBYnlR41LOtvLRCNtw7K3EFlbfB6hkPL-Swk5XNGbWZdTROmaTNzJhV-lWT0gGm6V1qWAK2qOZoIDa_3Ud0Gw\",\"e\":\"AQAB\"},{\"kty\":\"RSA\",\"kid\":\"W6WcOKB\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"2Zc5d0-zkZ5AKmtYTvxHc3vRc41YfbklflxG9SWsg5qXUxvfgpktGAcxXLFAd9Uglzow9ezvmTGce5d3DhAYKwHAEPT9hbaMDj7DfmEwuNO8UahfnBkBXsCoUaL3QITF5_DAPsZroTqs7tkQQZ7qPkQXCSu2aosgOJmaoKQgwcOdjD0D49ne2B_dkxBcNCcJT9pTSWJ8NfGycjWAQsvC8CGstH8oKwhC5raDcc2IGXMOQC7Qr75d6J5Q24CePHj_JD7zjbwYy9KNH8wyr829eO_G4OEUW50FAN6HKtvjhJIguMl_1BLZ93z2KJyxExiNTZBUBQbbgCNBfzTv7JrxMw\",\"e\":\"AQAB\"},{\"kty\":\"RSA\",\"kid\":\"fh6Bs8C\",\"use\":\"sig\",\"alg\":\"RS256\",\"n\":\"u704gotMSZc6CSSVNCZ1d0S9dZKwO2BVzfdTKYz8wSNm7R_KIufOQf3ru7Pph1FjW6gQ8zgvhnv4IebkGWsZJlodduTC7c0sRb5PZpEyM6PtO8FPHowaracJJsK1f6_rSLstLdWbSDXeSq7vBvDu3Q31RaoV_0YlEzQwPsbCvD45oVy5Vo5oBePUm4cqi6T3cZ-10gr9QJCVwvx7KiQsttp0kUkHM94PlxbG_HAWlEZjvAlxfEDc-_xZQwC6fVjfazs3j1b2DZWsGmBRdx1snO75nM7hpyRRQB4jVejW9TuZDtPtsNadXTr9I5NjxPdIYMORj9XKEh44Z73yfv0gtw\",\"e\":\"AQAB\"}]}";
    
public static Boolean appleJwtVerification(String token) {
        List<JSONObject> arr = getAuthKeys();
        if (arr == null) {
            return false;
        }
        //先取jwt中的header来匹配苹果公钥的kid
        java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
        String header = new String(decoder.decode(token.split("\\.")[0]));

        JSONObject headJsonObject = JSONObject.parseObject(header);

        for (JSONObject jsonObject : arr) {
            String headKid = headJsonObject.getString("kid");
            String headAlg = headJsonObject.getString("alg");
            String kid = jsonObject.getString("kid");
            String alg = jsonObject.getString("alg");
            if (headKid.equals(kid) && headAlg.equals(alg)) {
                // 验证
                try {
                    RsaJsonWebKey rsaJsonWebKey = new RsaJsonWebKey(jsonObject);
                    //获取公钥
                    RSAPublicKey rsaPublicKey = rsaJsonWebKey.getRsaPublicKey();

                    //根据密钥对生成RS256算法对象
                    Algorithm algorithm = Algorithm.RSA256(rsaPublicKey);

                    log.info("PublicKey: " + rsaPublicKey.getPublicExponent());

                    //解密时,使用gong钥生成算法对象
                    JWTVerifier verifier = JWT.require(algorithm)
                            .build();
                    //验证Token,verifier自动验证
                    DecodedJWT jwt = verifier.verify(token);
                    log.info("验证解析出来的apple信息:{}", jwt.getPayload());
                    return true;

                } catch (JWTVerificationException e) {
                    log.error("Token无法通过验证! " + e.getMessage());
                    return false;
                } catch (JoseException e) {
                    log.error("Token无法通过验证! " + e.getMessage());
                    return false;
                }
            }

        }

        return false;
    }

    private static List<JSONObject> getAuthKeys() {
        List<JSONObject> publicKeys = new ArrayList<>();

        try {
            String responseResult = HttpRequest.get(appleJwksUrl).setConnectionTimeout(3000).timeout(3000).execute().body();
            if (StrUtil.isNotBlank(responseResult)) {
                JSONObject jsonObject = JSONObject.parseObject(responseResult);
                JSONArray keys = jsonObject.getJSONArray("keys");
                for (int i = 0; i < keys.size(); i++) {
                    JSONObject jsonObject1 = keys.getJSONObject(i);
                    publicKeys.add(jsonObject1);
                }
            }
            log.info("苹果公钥" + responseResult);
        } catch (Exception e) {
            log.info("AppleLogin获取公钥发生错误,先用本地的公钥" + e);
            JSONObject jsonObject = JSONObject.parseObject(appleJwksCache);
            JSONArray keys = jsonObject.getJSONArray("keys");
            for (int i = 0; i < keys.size(); i++) {
                JSONObject jsonObject1 = keys.getJSONObject(i);
                publicKeys.add(jsonObject1);
            }
        }
        return publicKeys;
    }

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Security校验JWT Token的代码可以参考如下: 首先,需要创建JWT Token的验证过滤器类。该类继承自OncePerRequestFilter,并在doFilterInternal()方法中实现了JWT Token校验逻辑: ```java public class JwtTokenAuthenticationFilter extends OncePerRequestFilter { @Autowired private JwtTokenProvider jwtTokenProvider; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String token = jwtTokenProvider.resolveToken(request); try { if (token != null && jwtTokenProvider.validateToken(token)) { Authentication auth = jwtTokenProvider.getAuthentication(token); if (auth != null) { SecurityContextHolder.getContext().setAuthentication(auth); } } } catch (JwtException e) { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage()); return; } filterChain.doFilter(request, response); } } ``` 然后,需要创建JWT Token的提供者类,该类负责创建Token并验证Token: ```java @Component public class JwtTokenProvider { @Value("${jwt.secret}") private String secretKey; @Value("${jwt.token.validity}") private long validityInMilliseconds; private Key getSecretKey() { return Keys.hmacShaKeyFor(secretKey.getBytes()); } public String createToken(String username, List<Role> roles) { Claims claims = Jwts.claims().setSubject(username); claims.put("auth", roles.stream().map(role -> new SimpleGrantedAuthority(role.getAuthority())).filter(Objects::nonNull).collect(Collectors.toList())); Date now = new Date(); Date validity = new Date(now.getTime() + validityInMilliseconds); return Jwts.builder() .setClaims(claims) .setIssuedAt(now) .setExpiration(validity) .signWith(getSecretKey()) .compact(); } public Authentication getAuthentication(String token) { UserDetails userDetails = new User(getUsername(token), "", getAuthorities(token)); return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); } private String getUsername(String token) { return Jwts.parserBuilder().setSigningKey(getSecretKey()).build().parseClaimsJws(token).getBody().getSubject(); } private List<GrantedAuthority> getAuthorities(String token) { Claims claims = Jwts.parserBuilder() .setSigningKey(getSecretKey()) .build() .parseClaimsJws(token) .getBody(); List<LinkedHashMap<String, String>> roles = (List<LinkedHashMap<String, String>>) claims.get("auth"); return roles.stream().map(role -> new SimpleGrantedAuthority(role.get("authority"))).collect(Collectors.toList()); } public boolean validateToken(String token) { try { Jwts.parserBuilder().setSigningKey(getSecretKey()).build().parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { e.printStackTrace(); return false; } } public String resolveToken(HttpServletRequest req) { String bearerToken = req.getHeader("Authorization"); if (bearerToken != null && bearerToken.startsWith("Bearer ")) { return bearerToken.substring(7); } return null; } } ``` 最后,需要把上述过滤器类和提供者类添加到Spring Security的配置中: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtTokenProvider jwtTokenProvider; @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/api/v1/auth/login").permitAll() .anyRequest().authenticated() .and() .addFilterBefore(new JwtTokenAuthenticationFilter(jwtTokenProvider), UsernamePasswordAuthenticationFilter.class); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); } @Bean public UserDetailsService userDetailsService() { return new UserServiceImpl(); } } ``` 以上代码用来实现Spring Security校验JWT Token的功能,提供了创建Token校验Token和获取Token中存储的用户和权限信息等相关方法。您可以根据您的实际需求进行修改和调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值