spring security
@Configuration
@EnableResourceServer
public class AppWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private ZuulProperties zuulProperties;
@Autowired
private AuthenticationSuccessHandler appAuthenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler appAuthenticationFailureHandler;
@Autowired
private AccessDeniedHandler appAccessDeniedHandler;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.GET,zuulProperties.getAuth().toGetAdapter())
.permitAll()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST,zuulProperties.getAuth().toPostAdapter())
.permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling().accessDeniedHandler(appAccessDeniedHandler)
.and()
.csrf().disable();
}
spring oauth相关
@Configuration
@EnableAuthorizationServer
public class AppAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private final AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private ZuulProperties zuulProperties;
@Autowired
private TokenStore tokenStore ;
@Autowired(required = false)
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired(required = false)
private TokenEnhancer jwtTokenEnhancer;
@Autowired
private PasswordEncoder passwordEncoder;
public AppAuthorizationServerConfig(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
InMemoryClientDetailsServiceBuilder builder = clients.inMemory();
OAuth2ClientProperties[] clientProperties = zuulProperties.getOauth().getClients();
if(ArrayUtils.isNotEmpty(zuulProperties.getOauth().getClients())) {
for (OAuth2ClientProperties oAuth2ClientProperties : clientProperties) {
builder.withClient(oAuth2ClientProperties.getClientId())
.secret(oAuth2ClientProperties.getClientSecret())
//token有效时间
.accessTokenValiditySeconds(oAuth2ClientProperties.getAccessTokenValiditySeconds())
//验证模式
.authorizedGrantTypes("password","authorization_code","client_credentials","implicit","refresh_token")
//刷新时间
.refreshTokenValiditySeconds(3600*24*100)
//跳转地址
.redirectUris("ws.28ph.cn")
//权限
.scopes("all");
}
}
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore)
.userDetailsService(userDetailsService)
.reuseRefreshTokens(true);
if(jwtAccessTokenConverter != null && jwtTokenEnhancer!=null) {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> tokenEnhancers = new ArrayList<>();
tokenEnhancers.add(jwtTokenEnhancer);
tokenEnhancers.add(jwtAccessTokenConverter);
enhancerChain.setTokenEnhancers(tokenEnhancers);
endpoints
.tokenEnhancer(enhancerChain)
.accessTokenConverter(jwtAccessTokenConverter);
}
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.passwordEncoder(passwordEncoder)
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
问题的产生:我在spring security配置了几个不需要拦截的uri,但是加入spring oauth 全部被拦截了,如果删掉@EnableResourceServer会出现 发出来的token 认证不了url的问题。。
然后我想大不了不用spring oauth 自带的发token方式。然后我在spring security的成功handler上下发token ,以下是代码
/**
* 认证成功跳转
* @author w4837
*
*/
@Component(value = "AppAuthenticationSuccessHandler")
@Slf4j
public class AppAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationServerTokenServices authorizationServerTokenServices;
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Authentication authentication)
throws IOException, ServletException {
log.info("登陆成功");
String header = httpServletRequest.getHeader("Authorization");
//请求头包含Authorization 并且以"Basic "开始
if (header == null || !header.startsWith("Basic ")) {
throw new UnapprovedClientAuthenticationException("请求头中无Authorization信息");
}
try {
String[] tokens = extractAndDecodeHeader(header, httpServletRequest);
assert tokens.length == 2;
String clientId = tokens[0];
String clientSecret = tokens[1];
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
if(clientDetails == null) {
throw new UnapprovedClientAuthenticationException("clientId:"+clientId+"对应的信息不存在。");
}else if(!StringUtils.equals(clientSecret, clientDetails.getClientSecret())) {
throw new UnapprovedClientAuthenticationException("clientId:"+clientId+"对应的信息不匹配。");
}
@SuppressWarnings("unchecked")
TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_MAP, clientId, clientDetails.getScope(),"custom");
OAuth2Request auth2Request = tokenRequest.createOAuth2Request(clientDetails);
OAuth2Authentication auth2Authentication = new OAuth2Authentication(auth2Request, authentication);
OAuth2AccessToken createAccessToken = authorizationServerTokenServices.createAccessToken(auth2Authentication);
// 判断需要的返回类型
httpServletResponse.setContentType(ZuulAppConstant.CONTENT_TYPE_JSON);
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(createAccessToken));
} catch (Exception e) {
log.error(e.getMessage());
}
}
/**
* 解析header中编码后的数据
*
* @param header
* @param request
* @return
* @throws IOException
*/
private String[] extractAndDecodeHeader(String header, HttpServletRequest request) throws IOException {
byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
try {
decoded = Base64.decode(base64Token);
} catch (IllegalArgumentException e) {
throw new BadCredentialsException("Failed to decode basic authentication token");
}
String token = new String(decoded, "UTF-8");
int delim = token.indexOf(":");
if (delim == -1) {
throw new BadCredentialsException("Invalid basic authentication token");
}
return new String[] { token.substring(0, delim), token.substring(delim + 1) };
}
结果 启动还是报循环依赖的错误
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| appAuthorizationServerConfig defined in file [F:\yulece_aike_ideaword\app-management\app-management-zuul\target\classes\com\yulece\app\management\zuul\authorization\AppAuthorizationServerConfig.class]
↑ ↓
| appWebSecurityConfigurerAdapter (field private org.springframework.security.web.authentication.AuthenticationSuccessHandler com.yulece.app.management.zuul.authorization.AppWebSecurityConfigurerAdapter.appAuthenticationSuccessHandler)
↑ ↓
| AppAuthenticationSuccessHandler (field private org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices com.yulece.app.management.zuul.authorization.handler.AppAuthenticationSuccessHandler.defaultAuthorizationServerTokenServices)
↑ ↓
| org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration (field private java.util.List org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration.configurers)
└─────┘