java对接netcore identity4service 授权,解析token。
获取identity4service 公钥
http://*:5121/.well-known/openid-configuration/jwks
如果identity4service
使用临时加密的方式(AddDeveloperSigningCredential
,AddTemporarySigningCredential
),会导致identity4service
每次重启会生成一对新的证书,所以每次获取公钥要保证是最新的。
也可以给identity4service
配置证书。
Startup.cs
1 2 3 4 5 6 7 8 9 10 11
| services.AddIdentityServer() .AddSigningCredential(new X509Certificate2(Path.Combine(basePath, configuration["Certificates:Path"]), configuration["Certificates:Password"])) .AddInMemoryApiResources(Config.GetApis()) .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryClients(Config.GetClients()) .AddProfileService<ProfileService>() .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>() .AddCustomAuthorizeRequestValidator<CustomAuthorizeRequestValidator>();
|
application.json
1 2 3 4 5 6
| { "Certificates": { "Path": "Certificates\\IS4.pfx", "Password": "xxxxxx" } }
|
获取公钥
http://172.16.100.177:5121/.well-known/openid-configuration/jwks
1
| {"keys":[{"kty":"RSA","use":"sig","kid":"800740ecb2919cf1bd943da1d7e1c38b","e":"AQAB","n":"wSxc3gNHN7lo9C5LC0Ewoh6aERStezc2HofougTOvfzLgFFWBNBWkCe7X32em1MGzpEguuA90myubLjSvxYvkRq3YJXzwpapAtU32sciXdcPT-d4Qy-RQjQ269pEpLqsSpSYBBC-LHKGTg01AaI_41NS-lw3d_G3DCcT5RaBoMPds5UpOJqHrLLPIKgMGarE7XmPs9w0NyPHz7RU_MHn9UEWTzOByiKBnTZI_nGVEebCGqIdREq8NZnfTjbGrMiRt2i7gY7Cl7K39mwWoovNwvg_p9KscWykiTJzsU2M6EHskRECOfoZ65FHvUHXnZ3IK-VxJ2GqLW_-5eK3lUPY6Q","alg":"RS256"}]}
|
java 解析验证token
前端获取identity4service
token,调用接口;java服务端截取token字符串,获取公钥来做验证。
拦截器代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| public class AuthenticationInterceptor implements HandlerInterceptor { @Autowired private UserAuth userAuth;
@Value("${config.defaultUserId}") private String defaultUserId;
@Value("${config.umsPublicKey}") private String umsPublicKey;
@Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception { if (!(object instanceof HandlerMethod)) { return true; }
HandlerMethod handlerMethod = (HandlerMethod) object; Method method = handlerMethod.getMethod(); UserToken userToken = method.getAnnotation(UserToken.class);
if (userToken != null) { String token = httpServletRequest.getHeader("Authorization");
if (token == null) { httpServletResponse.setStatus(401); throw new DataApiException(HttpStatusEnum.Token401); }
token = token.replace("Bearer ", "");
DecodedJWT verifier = JWT.decode(token);
try { ConfigurableJWTProcessor jwtProcessor = new DefaultJWTProcessor(); ClassPathResource classPathResource = new ClassPathResource(umsPublicKey); ByteArrayInputStream is = new ByteArrayInputStream(umsPublicKey.getBytes()); JWKSource keySource = new ImmutableJWKSet(JWKSet.load(is)); JWSAlgorithm expectedJWSAlg = JWSAlgorithm.RS256; JWSKeySelector keySelector = new JWSVerificationKeySelector(expectedJWSAlg, keySource); jwtProcessor.setJWSKeySelector(keySelector); SecurityContext ctx = null; jwtProcessor.process(token, ctx); } catch (Exception e) { throw new DataApiException(HttpStatusEnum.Token401, "token签名验证失败!"); }
Date a = verifier.getExpiresAt(); if (a.getTime() < System.currentTimeMillis()) { httpServletResponse.setStatus(401); throw new DataApiException(HttpStatusEnum.Token401, "token时间过期!"); } String userId = verifier.getSubject(); userAuth.setUserId(userId); } else { userAuth.setUserId(defaultUserId); } return true; } }
|
InterceptorConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.soyuan.dataapi.interfaces.interceptor;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration public class InterceptorConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authenticationInterceptor()) .addPathPatterns("/**"); } @Bean public AuthenticationInterceptor authenticationInterceptor() { return new AuthenticationInterceptor(); } }
|
UserToken.java
1 2 3 4 5 6 7 8 9 10 11 12
| package com.soyuan.dataapi.interfaces.interceptor;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface UserToken { }
|
接口使用
controller
使用增加 @UserToken
1 2 3 4 5 6
| @GetMapping("/GetApiGroupsByUserId") @UserToken public ApiResult<List<ApiGroupDto>> GetApiGroupsByUserId(@RequestParam(required = false) String groupName) { return ApiResult.ok(apiGroupService.GetApiGroupList(groupName)); }
|