Spring Security OAuth2 自定义授权实现微信小程序登录实现
·
【Spring Security OAuth2 自定义授权实现微信小程序登录实现】
在Spring Security OAuth2框架下实现微信小程序登录,需要自定义授权流程。微信小程序登录与传统的OAuth2流程有所不同,主要区别在于微信使用code换取session_key和openid的机制。
实现步骤
1. 添加依赖
首先确保你的项目中包含Spring Security OAuth2和微信相关SDK:
<!-- Spring Security OAuth2 -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.6.8</version>
</dependency>
<!-- 微信小程序Java SDK -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.1.0</version>
</dependency>
2. 配置微信小程序参数
在application.yml中添加配置:
wechat:
miniapp:
appid: your_appid
secret: your_secret
3. 创建自定义TokenGranter
public class WechatMiniAppTokenGranter extends AbstractTokenGranter {
private static final String GRANT_TYPE = "wechat_miniapp";
private final WxMaService wxMaService;
public WechatMiniAppTokenGranter(AuthorizationServerTokenServices tokenServices,
ClientDetailsService clientDetailsService,
OAuth2RequestFactory requestFactory,
WxMaService wxMaService) {
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
this.wxMaService = wxMaService;
}
@Override
protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, TokenRequest tokenRequest) {
Map<String, String> parameters = new LinkedHashMap<>(tokenRequest.getRequestParameters());
// 获取微信小程序code
String code = parameters.get("code");
try {
// 用code换取session_key和openid
WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
String openid = session.getOpenid();
// 根据openid查询或创建用户
UserDetails userDetails = loadOrCreateUserByOpenid(openid);
// 构建用户认证信息
UsernamePasswordAuthenticationToken userAuth = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
// 构建OAuth2请求
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, tokenRequest);
return new OAuth2Authentication(storedOAuth2Request, userAuth);
} catch (WxErrorException e) {
throw new InvalidGrantException("微信登录失败: " + e.getMessage());
}
}
private UserDetails loadOrCreateUserByOpenid(String openid) {
// 实现根据openid查询或创建用户的逻辑
// 这里应该是你的业务逻辑
// ...
}
}
4. 配置授权服务器
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private WxMaService wxMaService;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
// 添加自定义的TokenGranter
endpoints.tokenGranter(tokenGranter(endpoints));
endpoints.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
private TokenGranter tokenGranter(AuthorizationServerEndpointsConfigurer endpoints) {
List<TokenGranter> granters = new ArrayList<>(Collections.singletonList(endpoints.getTokenGranter()));
// 添加微信小程序授权模式
granters.add(new WechatMiniAppTokenGranter(
endpoints.getTokenServices(),
endpoints.getClientDetailsService(),
endpoints.getOAuth2RequestFactory(),
wxMaService
));
return new CompositeTokenGranter(granters);
}
// 其他配置...
}
5. 客户端调用方式
微信小程序前端获取code后,调用后端接口:
wx.login({
success(res) {
if (res.code) {
// 发送code到后端
wx.request({
url: 'http://your-server/oauth/token',
method: 'POST',
data: {
grant_type: 'wechat_miniapp',
code: res.code,
client_id: 'your_client_id',
client_secret: 'your_client_secret'
},
success(res) {
console.log('登录成功', res.data);
}
});
}
}
});
6. 后端响应
成功响应将返回标准的OAuth2令牌:
{
"access_token": "xxx",
"token_type": "bearer",
"refresh_token": "xxx",
"expires_in": 3600,
"scope": "read write"
}
安全注意事项
验证客户端凭证:确保只有受信任的客户端可以使用此授权类型
保护用户数据:不要将openid等敏感信息返回给客户端
防止重放攻击:微信的code只能使用一次,确保你的实现符合这一要求
会话管理:合理设置access_token和refresh_token的过期时间
扩展功能
用户信息解密:如果需要获取用户手机号等加密信息,可以实现解密逻辑
多小程序支持:可以通过在请求中添加appid参数来支持多个小程序
JWT令牌:可以考虑使用JWT代替默认的令牌格式,包含更多用户信息
更多推荐



所有评论(0)