springsecurity加入第三方授权认证

2023年 8月 13日 80.1k 0

由于博主在做一个校园项目的时候使用啦spring security安全框架,然后在整合第三方授权登录的时候,被困扰了好几天,就想着发一下这个文章,希望能给大家带来帮助。

第三方授权登录的原理,我就不在这里过多阐述了(作者也是小白,怕给你们带入歧途),大家不熟悉或者不了解的可以取哔哩哔哩看一下不良人的springsecurity教程,后面的课程就是讲述的第三方授权登录的知识。也可以看一下《深入浅出spring security》这本书。

单纯的springboot项目的话可以直接使用justauth这个第三方框架,集成啦许多的第三方登录的接口,只用自己调用一下api就能解决第三方授权登录的问题。

问题描述

现在大多数软件和web网站都会加入第三方授权登录的功能,以方便提高用户的体验。此时就给我们后端开发的人带来了极大的烦恼。

由于此项目加入了springsecurity框架,此时就不能使用justauth这个框架了,这个框架关于springsecurity的解决还没完善。所以就要使用springsecurity自带的oauth2认证过滤器(其实你会发现非常简单就能解决了)。

详细步骤(以gitee举例)

1. 进入官网点击设置
点击头像设置
2. 向下翻转,点击第三方应用
在这里插入图片描述
3. 点击创建应用后就进入下面这个界面
在这里插入图片描述
4. 然后把标星的给填上
在这里插入图片描述
注意回调地址格式不要写错,否则springsecurity识别不出
http://IP地址:端口号/login/oauth2/code/应用名称
5. 在springboot里加入配置

security:
    oauth2:
      client:
        registration:
          gitee:
            client-id: #授权id
            client-secret:  #授权密钥
            authorization-grant-type: authorization_code
            redirect-uri:  #回调地址
            client-name: gitee #应用名称
            scope: user_info
        provider:
          gitee:
            authorization-uri: https://gitee.com/oauth/authorize
            token-uri: https://gitee.com/oauth/token
            user-info-uri: https://gitee.com/api/v5/user
            user-name-attribute: gitee

6. 此时要创建一个实体类,这个实体类是接收第三方应用传输的授权信息的。每个应用的授权信息都不同,大家可以在网上单独看一下对应的官网都会返回什么授权信息。

@NoArgsConstructor
@AllArgsConstructor
@Data
public class OAuth2UserDTO implements OAuth2User {
private String source;
private String id;
private String name;
private String email;
private String avatar;
@JsonIgnore
@JSONField(serialize = false)
private List authorities= AuthorityUtils.createAuthorityList("ROLE_USER");
@JsonIgnore
@JSONField(serialize = false)
private Map attributes;
@Override
public Map getAttributes() {
if (attributes==null){
attributes=new HashMap();
attributes.put("id",this.getId());
attributes.put("name",this.getName());
attributes.put("email",this.getEmail());
}

return attributes;
}

@Override
public Collection> requestEntityConverter = new OAuth2UserRequestEntityConverter();
private RestOperations restOperations;

public CustomOAuth2UserService() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
this.restOperations = restTemplate;
}

@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
Assert.notNull(userRequest, "userRequest cannot be null");
if (!StringUtils
.hasText(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri())) {
OAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_INFO_URI_ERROR_CODE,
"Missing required UserInfo Uri in UserInfoEndpoint for Client Registration: "
+ userRequest.getClientRegistration().getRegistrationId(),
null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
String userNameAttributeName = userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint()
.getUserNameAttributeName();
if (!StringUtils.hasText(userNameAttributeName)) {
OAuth2Error oauth2Error = new OAuth2Error(MISSING_USER_NAME_ATTRIBUTE_ERROR_CODE,
"Missing required "user name" attribute name in UserInfoEndpoint for Client Registration: "
+ userRequest.getClientRegistration().getRegistrationId(),
null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
RequestEntity request = this.requestEntityConverter.convert(userRequest);
ResponseEntity response = getResponse(userRequest, request);
Map userAttributes = response.getBody();
Set authorities = new LinkedHashSet();
authorities.add(new OAuth2UserAuthority(userAttributes));
OAuth2AccessToken token = userRequest.getAccessToken();
for (String authority : token.getScopes()) {
authorities.add(new SimpleGrantedAuthority("SCOPE_" + authority));
}
//更换为自定义的OAuth2User实现
return new OAuth2UserDTO(userAttributes, userNameAttributeName);
}

private ResponseEntity getResponse(OAuth2UserRequest userRequest, RequestEntity request) {
OAuth2Error oauth2Error;
try {
return this.restOperations.exchange(request, PARAMETERIZED_RESPONSE_TYPE);
} catch (OAuth2AuthorizationException var6) {
oauth2Error = var6.getError();
StringBuilder errorDetails = new StringBuilder();
errorDetails.append("Error details: [");
errorDetails.append("UserInfo Uri: ").append(userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri());
errorDetails.append(", Error Code: ").append(oauth2Error.getErrorCode());
if (oauth2Error.getDescription() != null) {
errorDetails.append(", Error Description: ").append(oauth2Error.getDescription());
}

errorDetails.append("]");
oauth2Error = new OAuth2Error("invalid_user_info_response", "An error occurred while attempting to retrieve the UserInfo Resource: " + errorDetails.toString(), (String)null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), var6);
} catch (UnknownContentTypeException var7) {
String errorMessage = "An error occurred while attempting to retrieve the UserInfo Resource from '" + userRequest.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri() + "': response contains invalid content type '" + var7.getContentType().toString() + "'. The UserInfo Response should return a JSON object (content type 'application/json') that contains a collection of name and value pairs of the claims about the authenticated End-User. Please ensure the UserInfo Uri in UserInfoEndpoint for Client Registration '" + userRequest.getClientRegistration().getRegistrationId() + "' conforms to the UserInfo Endpoint, as defined in OpenID Connect 1.0: 'https://openid.net/specs/openid-connect-core-1_0.html#UserInfo'";
OAuth2Error oAuth2Error = new OAuth2Error("invalid_user_info_response", errorMessage, (String)null);
throw new OAuth2AuthenticationException(oAuth2Error, oAuth2Error.toString(), var7);
} catch (RestClientException var8) {
oauth2Error = new OAuth2Error("invalid_user_info_response", "An error occurred while attempting to retrieve the UserInfo Resource: " + var8.getMessage(), (String)null);
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString(), var8);
}
}

public final void setRequestEntityConverter(Converter

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论