使用Spring Security Outh2启动报错,循环依赖

dx8809055 2018-10-20 09:57:21
请各位大佬帮忙看看,使用Spring Security Outh2权限框架,启动报错,但是本地是可以启动的,现在因为需求要定制一个JWT的token,不走jar包里面的Outh2登录接口
1:首先错误

2:ItsamsAuthorizationConfig代码

@Configuration
@Order(Integer.MIN_VALUE)
@EnableAuthorizationServer
public class ItsamsAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
private final static Logger log = LoggerFactory.getLogger(ItsamsAuthorizationConfig.class);
@Autowired
private AuthServerConfig authServerConfig;

private final AuthenticationManager authenticationManager;

private final UserDetailsService userDetailsService;


@Autowired
public ItsamsAuthorizationConfig(final AuthenticationManager authenticationManager,
final UserDetailsService userDetailsService) {

this.authenticationManager = authenticationManager;
this.userDetailsService = userDetailsService;
this.itsamsWebResponseExceptionTranslator = itsamsWebResponseExceptionTranslator;
log.error("11authenticationManager......................." + authenticationManager);
}

@Override
public void configure(final ClientDetailsServiceConfigurer clients) {
log.error("22authenticationManager......................." + authenticationManager);
try {
clients.inMemory().withClient(authServerConfig.getClientId()).secret(authServerConfig.getClientSecret())
.authorizedGrantTypes(SecurityConstants.REFRESH_TOKEN, SecurityConstants.PASSWORD,
SecurityConstants.AUTHORIZATION_CODE)
.scopes(authServerConfig.getScope());
} catch (final Exception e) {
throw new BusinessException(ExceptionEnum.EXECUTE_AUTH_EXCP.setExceptionMsg("权限异常"));
}
}

@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
log.error("33authenticationManager......................." + authenticationManager);
endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter())
.authenticationManager(authenticationManager)
.reuseRefreshTokens(false).userDetailsService(userDetailsService);
}

@Override
public void configure(final AuthorizationServerSecurityConfigurer security) {
security.allowFormAuthenticationForClients().tokenKeyAccess("isAuthenticated()")
.checkTokenAccess("permitAll()");
}

@Bean
public TokenStore jwtTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
final JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey(CommonConstant.SIGN_KEY);
return jwtAccessTokenConverter;
}

3:ItsamsSecurityConfigurerAdapter
@Configuration
@EnableWebSecurity
public class ItsamsSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private FilterUrlsPropertiesConifg filterUrlsPropertiesConifg;

// @Autowired
// private MobileSecurityConfigurer mobileSecurityConfigurer;
@Autowired
private SSOSecurityConfigurer sSOSecurityConfigurer;

@Override
public void configure(final HttpSecurity http) {
try {
final ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
.formLogin().loginPage("/authentication/require").loginProcessingUrl("/authentication/form").and()
.authorizeRequests();
for (final String url : filterUrlsPropertiesConifg.getAnon()) {
registry.antMatchers(url).permitAll();
}
registry.anyRequest().authenticated().and().csrf().disable();
http.apply(sSOSecurityConfigurer);
} catch (final Exception e) {
throw new BusinessException(ExceptionEnum.EXECUTE_AUTH_EXCP.setExceptionMsg("权限异常"));
}

}

}

4:MobileLoginSuccessHandler
@Component
public class MobileLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
public static final String BASIC_ = "Basic ";
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ClientDetailsService clientDetailsService;
// @Autowired
// private AuthorizationServerTokenServices authorizationServerTokenServices;
@Autowired
private TokenStore tokenStore;

private final static boolean supportRefreshToken = true;
private final int refreshTokenValiditySeconds = 60 * 60 * 24 * 30;

private final int accessTokenValiditySeconds = 60 * 60 * 12;
@Autowired
private TokenEnhancer accessTokenEnhancer;

/**
* Called when a user has been successfully authenticated. 调用spring security
* oauth API 生成 oAuth2AccessToken
*
* @param request
* the request which caused the successful authentication
* @param response
* the response
* @param authentication
* the <tt>Authentication</tt> object which was created during
*/
@Override
public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
final Authentication authentication) {
final String header = request.getHeader("Authorization");

if (header == null || !header.startsWith(BASIC_)) {
throw new UnapprovedClientAuthenticationException("请求头中client信息为空");
}

try {
final String[] tokens = extractAndDecodeHeader(header);
assert tokens.length == 2;
final String clientId = tokens[0];
final String clientSecret = tokens[1];
final JSONObject params = new JSONObject();
params.put("clientId", clientId);
params.put("clientSecret", clientSecret);
params.put("authentication", authentication);

final ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
final TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId, clientDetails.getScope(),
"sso");
final OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);

final OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
final OAuth2AccessToken oAuth2AccessToken = createAccessToken(oAuth2Authentication);
// final OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices
// .createAccessToken(oAuth2Authentication);
logger.info("获取token 成功:{}", oAuth2AccessToken.getValue());

response.setCharacterEncoding(CommonConstant.UTF8);
response.setContentType(CommonConstant.CONTENT_TYPE);
final PrintWriter printWriter = response.getWriter();
printWriter.append(objectMapper.writeValueAsString(oAuth2AccessToken));
} catch (final IOException e) {
throw new BadCredentialsException("Failed to decode basic authentication token");
}
}

/**
* Decodes the header into a username and password.
*
* @throws BadCredentialsException
* if the Basic header is not present or is not valid Base64
*/
private String[] extractAndDecodeHeader(final String header) throws IOException {

final byte[] base64Token = header.substring(6).getBytes("UTF-8");
byte[] decoded;
try {
decoded = Base64.decode(base64Token);
} catch (final IllegalArgumentException e) {
throw new BadCredentialsException("Failed to decode basic authentication token");
}

final String token = new String(decoded, CommonConstant.UTF8);

final 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) };
}

@Transactional
public OAuth2AccessToken createAccessToken(final OAuth2Authentication authentication)
throws AuthenticationException {

final OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
OAuth2RefreshToken refreshToken = null;
if (existingAccessToken != null) {
if (existingAccessToken.isExpired()) {
if (existingAccessToken.getRefreshToken() != null) {
refreshToken = existingAccessToken.getRefreshToken();
// The token store could remove the refresh token when the
// access token is removed, but we want to
// be sure...
tokenStore.removeRefreshToken(refreshToken);
}
tokenStore.removeAccessToken(existingAccessToken);
} else {
// Re-store the access token in case the authentication has changed
tokenStore.storeAccessToken(existingAccessToken, authentication);
return existingAccessToken;
}
}

// Only create a new refresh token if there wasn't an existing one
// associated with an expired access token.
// Clients might be holding existing refresh tokens, so we re-use it in
// the case that the old access token
// expired.
if (refreshToken == null) {
refreshToken = createRefreshToken(authentication);
}
// But the refresh token itself might need to be re-issued if it has
// expired.
else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
final ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
refreshToken = createRefreshToken(authentication);
}
}

final OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
tokenStore.storeAccessToken(accessToken, authentication);
// In case it was modified
refreshToken = accessToken.getRefreshToken();
if (refreshToken != null) {
tokenStore.storeRefreshToken(refreshToken, authentication);
}
return accessToken;

}
...全文
698 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
lietobrain 2020-03-29
  • 打赏
  • 举报
回复
ItsamsSecurityConfigurerAdapter<--ItsamsAuthorizationConfig<--MobileLoginSuccessHandler<--SSOSecurityConfigurer <--ItsamsSecurityConfigurerAdapter; 形成了闭环,spring其实已经做好很棒的解决闭环问题,出现循环问题,大多是因为使用了构造函数,例如你这里的 @Autowired public ItsamsAuthorizationConfig(final AuthenticationManager authenticationManager, final UserDetailsService userDetailsService) { } 建议是直接用set的方式就行了。。 你上传缺少了一个SSOSecurityConfigurer;不过两年前的问题,估计你早就解决了。。
dx8809055 2018-10-20
  • 打赏
  • 举报
回复
大佬们帮帮忙,已经弄了两天了,一直没弄好

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧