提交 1651f97e 编写于 作者: zlt2000's avatar zlt2000

优化zlt-uaa原生的授权接口返回值为统一的json格式,并修复开始多租户时原生的授权接口和refresh_token接口丢失租户id导致角色取不到的问题

上级 71bc1288
package com.central.oauth.config;
import com.central.common.constant.SecurityConstants;
import com.central.oauth.filter.LoginProcessSetTenantFilter;
import com.central.oauth.handler.OauthLogoutSuccessHandler;
import com.central.oauth.mobile.MobileAuthenticationSecurityConfig;
import com.central.oauth.openid.OpenIdAuthenticationSecurityConfig;
......@@ -19,7 +20,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import javax.annotation.Resource;
......@@ -95,6 +96,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
.and()
.apply(mobileAuthenticationSecurityConfig)
.and()
.addFilterBefore(new LoginProcessSetTenantFilter(), UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
// 解决不允许显示在iframe的问题
.headers().frameOptions().disable().cacheControl();
......
......@@ -100,6 +100,7 @@ public class OAuth2Controller {
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
oAuth2Authentication.setAuthenticated(true);
TenantContextHolder.clear();
ResponseUtil.responseSucceed(objectMapper, response, oAuth2AccessToken);
} catch (BadCredentialsException | InternalAuthenticationServiceException e) {
exceptionHandler(response, badCredenbtialsMsg);
......
package com.central.oauth.filter;
import cn.hutool.core.util.ArrayUtil;
import com.alibaba.nacos.common.util.HttpMethod;
import com.central.common.constant.SecurityConstants;
import com.central.common.context.TenantContextHolder;
import org.springframework.security.web.savedrequest.DefaultSavedRequest;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 设置租户id过滤器
*
* @author zlt
* @date 2020/3/29
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
public class LoginProcessSetTenantFilter extends OncePerRequestFilter {
private static final String SAVED_REQUEST = "SPRING_SECURITY_SAVED_REQUEST";
private RequestMatcher requiresAuthenticationRequestMatcher;
public LoginProcessSetTenantFilter() {
requiresAuthenticationRequestMatcher = new AntPathRequestMatcher(SecurityConstants.OAUTH_LOGIN_PRO_URL, HttpMethod.POST);
}
/**
* 返回true代表不执行过滤器,false代表执行
*/
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
if (requiresAuthentication(request)) {
return false;
}
return true;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
try {
DefaultSavedRequest savedRequest = (DefaultSavedRequest)request.getSession().getAttribute(SAVED_REQUEST);
if (savedRequest != null) {
String[] clientIds = savedRequest.getParameterValues("client_id");
if (ArrayUtil.isNotEmpty(clientIds)) {
//保存租户id
TenantContextHolder.setTenant(clientIds[0]);
}
}
chain.doFilter(request, response);
} finally {
TenantContextHolder.clear();
}
}
private boolean requiresAuthentication(HttpServletRequest request) {
return requiresAuthenticationRequestMatcher.matches(request);
}
}
package com.central.oauth.filter;
import com.central.common.constant.SecurityConstants;
import com.central.common.context.TenantContextHolder;
import com.central.common.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Component;
import java.security.Principal;
import java.util.Map;
/**
* oauth-token拦截器
* 1. 赋值租户
* 2. 统一返回token格式
*
* @author zlt
* @date 2020/3/29
* <p>
* Blog: https://blog.csdn.net/zlt2000
* Github: https://github.com/zlt2000
*/
@Slf4j
@Component
@Aspect
public class OauthTokenAspect {
@Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {
try {
Object[] args = joinPoint.getArgs();
Principal principal = (Principal) args[0];
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
String clientId = getClientId(principal);
Map<String, String> parameters = (Map<String, String>) args[1];
String grantType = parameters.get(OAuth2Utils.GRANT_TYPE);
//保存租户id
TenantContextHolder.setTenant(clientId);
Object proceed = joinPoint.proceed();
if (SecurityConstants.AUTHORIZATION_CODE.equals(grantType)) {
/*
如果使用 @EnableOAuth2Sso 注解不能修改返回格式,否则授权码模式可以统一改
因为本项目的 sso-demo/ss-sso 里面使用了 @EnableOAuth2Sso 注解,所以这里就不修改授权码模式的token返回值了
*/
return proceed;
} else {
ResponseEntity<OAuth2AccessToken> responseEntity = (ResponseEntity<OAuth2AccessToken>) proceed;
OAuth2AccessToken body = responseEntity.getBody();
return ResponseEntity
.status(HttpStatus.OK)
.body(Result.succeed(body));
}
} catch (Exception e) {
return ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(Result.failed(e.getMessage()));
} finally {
TenantContextHolder.clear();
}
}
private String getClientId(Principal principal) {
Authentication client = (Authentication) principal;
if (!client.isAuthenticated()) {
throw new InsufficientAuthenticationException("The client is not authenticated.");
}
String clientId = client.getName();
if (client instanceof OAuth2Authentication) {
clientId = ((OAuth2Authentication) client).getOAuth2Request().getClientId();
}
return clientId;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册