问题描述
我有一个应用程序,它使用 Spring Boot 作为后端,使用 ReactJS 作为前端。我在登录时使用了 Linkedin OAuth 来授权用户。
当有人登录时,会创建 JSESSIONID
cookie 并将其存储在后端域 (http://www.my-backend.com
) 中。要在前端使用 API,我需要在前端 (JSESSIONID
) 中存储 http://www.my-frontend.com
。有人可以帮我解决这个问题吗?
我想要实现的目标:也在前端域中创建 JSESSIONID
cookie。
Application.yml
spring:
thymeleaf:
cache: false
security:
oauth2:
client:
registration:
linkedin:
client-id: ${CLIENT_ID}
client-secret: ${CLIENT-SECRET}
client-authentication-method: post
authorization-grant-type: authorization_code
redirect-uri: "http://my-frontend.com"
scope: r_liteprofile,r_emailaddress
client-name: Linkedin
provider:
linkedin:
authorization-uri: https://www.linkedin.com/oauth/v2/authorization
token-uri: https://www.linkedin.com/oauth/v2/accesstoken
user-info-uri: https://api.linkedin.com/v2/me?projection=(id,localizedFirstName,localizedLastName,profilePicture(displayImage~:playableStreams))
user-name-attribute: id
email-address-uri: https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MysqL5InnoDBDialect
hibernate:
ddl-auto: update
datasource:
url: jdbc:MysqL://${DB_URL}/${DB_NAME}?allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8
username: ${DB_USER_NAME}
password: ${DB_USER_PASSWORD}
jmx:
unique-names: true
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/api/admin/**")
.hasAnyAuthority("ADMIN")
.antMatchers("/api/programs")
.permitAll()
.antMatchers("/api/**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling()
.authenticationEntryPoint(
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)
)
.and()
.oauth2Login()
.failureHandler(new AuthFailureHandler())
.tokenEndpoint()
.accesstokenResponseClient(authorizationCodetokenResponseClient());
}
private OAuth2AccesstokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodetokenResponseClient() {
OAuth2AccesstokenResponseHttpMessageConverter converter = new OAuth2AccesstokenResponseHttpMessageConverter();
converter.setTokenResponseConverter(new AuthAccesstokenResponseConverter());
RestTemplate restTemplate = new RestTemplate(
Arrays.asList(new FormHttpMessageConverter(),converter)
);
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
DefaultAuthorizationCodetokenResponseClient responseClient = new DefaultAuthorizationCodetokenResponseClient();
responseClient.setRestOperations(restTemplate);
return responseClient;
}
private static class AuthFailureHandler
implements AuthenticationFailureHandler {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onAuthenticationFailure(
HttpServletRequest request,HttpServletResponse response,AuthenticationException exception
)
throws IOException,servletexception {
Map<String,Object> data = new HashMap<>();
response.setContentType("application/json");
response.setStatus(HttpStatus.UNAUTHORIZED.value());
data.put("exception",exception.getMessage());
response.getoutputStream().println(objectMapper.writeValueAsstring(data));
}
}
}
AuthAccesstokenResponseConverter.java
public class AuthAccesstokenResponseConverter
implements Converter<Map<String,String>,OAuth2AccesstokenResponse> {
private static final Set<String> TOKEN_RESPONSE_ParaMETER_NAMES
= Stream.of(OAuth2ParameterNames.ACCESS_TOKEN,OAuth2ParameterNames.TOKEN_TYPE,OAuth2ParameterNames.EXPIRES_IN,OAuth2ParameterNames.REFRESH_TOKEN,OAuth2ParameterNames.ScopE)
.collect(Collectors.toSet());
private OAuth2Accesstoken.TokenType defaultAccesstokenType = OAuth2Accesstoken.TokenType.BEARER;
@Override
public OAuth2AccesstokenResponse convert(Map<String,String> tokenResponseParameters) {
String accesstoken = tokenResponseParameters.get(OAuth2ParameterNames.ACCESS_TOKEN);
OAuth2Accesstoken.TokenType accesstokenType = defaultAccesstokenType;
if (OAuth2Accesstoken.TokenType.BEARER
.getValue().equalsIgnoreCase(tokenResponseParameters
.get(OAuth2ParameterNames.TOKEN_TYPE))) {
accesstokenType = OAuth2Accesstoken.TokenType.BEARER;
}
long expiresIn = 0;
if (tokenResponseParameters.containsKey(OAuth2ParameterNames.EXPIRES_IN)) {
expiresIn = Long.parseLong(tokenResponseParameters
.get(OAuth2ParameterNames.EXPIRES_IN));
}
Set<String> scopes = Collections.emptySet();
if (tokenResponseParameters.containsKey(OAuth2ParameterNames.ScopE)) {
String scope = tokenResponseParameters.get(OAuth2ParameterNames.ScopE);
scopes = Arrays.stream(StringUtils.delimitedListToStringArray(scope," "))
.collect(Collectors.toSet());
}
Map<String,Object> additionalParameters = new LinkedHashMap<>();
tokenResponseParameters.entrySet().stream()
.filter(e -> !TOKEN_RESPONSE_ParaMETER_NAMES.contains(e.getKey()))
.forEach(e -> additionalParameters.put(e.getKey(),e.getValue()));
return OAuth2AccesstokenResponse.withToken(accesstoken)
.tokenType(accesstokenType)
.expiresIn(expiresIn)
.scopes(scopes)
.additionalParameters(additionalParameters)
.build();
}
public final void setDefaultAccesstokenType(OAuth2Accesstoken.TokenType
defaultAccesstokenType) {
Assert.notNull(defaultAccesstokenType,"defaultAccesstokenType cannot be null");
this.defaultAccesstokenType = defaultAccesstokenType;
}
}
WebClientConfig.java
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient(ClientRegistrationRepository clientRegistrationRepository,OAuth2AuthorizedClientRepository authorizedClientRepository) {
ServletoAuth2AuthorizedClientExchangeFilterFunction oauth2 =
new ServletoAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepository,authorizedClientRepository);
return WebClient.builder()
.apply(oauth2.oauth2Configuration())
.build();
}
}
完整代码在这里:https://github.com/piumal1999/scholarx
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)