如何将Spring Bean OAuth集成从XML配置转为Java注解配置
Got it, let's convert your Spring OAuth2 XML configuration to annotation-based code step by step. I'll split this into logical components to match your original setup, so you can map each XML bean directly to the annotated code.
1. Core Web Security Configuration
This class handles the authentication managers and client credentials filter, corresponding to your <sec:authentication-manager> beans and clientCredentialsTokenEndpointFilter:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private ClientDetailsService clientDetailsService; // Maps to the `clientAuthenticationManager` bean @Bean public AuthenticationManager clientAuthenticationManager() throws Exception { return authenticationManagerBean(); } // Maps to `clientCredentialsTokenEndpointFilter` @Bean public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception { ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter(); filter.setAuthenticationManager(clientAuthenticationManager()); return filter; } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // In-memory user store matching your `<sec:user-service>` setup auth.inMemoryAuthentication() .withUser("arip") .password("{noop}passw0rd") // {noop} tells Spring Security to use plain text (demo only!) .authorities("ROLE_USER"); // Client authentication provider using ClientDetailsUserDetailsService auth.authenticationProvider(clientAuthenticationProvider()); } @Bean public AuthenticationProvider clientAuthenticationProvider() { ClientDetailsUserDetailsService userDetailsService = new ClientDetailsUserDetailsService(clientDetailsService); DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(NoOpPasswordEncoder.getInstance()); // Replace with BCrypt in production return provider; } }
2. OAuth2 Helper Beans (Entry Points, Access Denied Handler, Decision Manager)
This class defines the beans for authentication entry points, access denied handling, and the access decision manager:
@Configuration public class OAuth2ConfigBeans { // Maps to `oauthAuthenticationEntryPoint` @Bean public OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setRealmName("test"); return entryPoint; } // Maps to `clientAuthenticationEntryPoint` @Bean public OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint() { OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint(); entryPoint.setRealmName("test/client"); entryPoint.setTypeName("Basic"); return entryPoint; } // Maps to `oauthAccessDeniedHandler` @Bean public OAuth2AccessDeniedHandler oauthAccessDeniedHandler() { return new OAuth2AccessDeniedHandler(); } // Maps to `accessDecisionManager` @Bean public AccessDecisionManager accessDecisionManager() { List<AccessDecisionVoter<? extends Object>> voters = new ArrayList<>(); voters.add(new ScopeVoter()); voters.add(new RoleVoter()); voters.add(new AuthenticatedVoter()); return new UnanimousBased(voters); } }
3. Authorization Server Configuration
This class replaces your /oauth/token HTTP configuration and token-related beans, using @EnableAuthorizationServer:
@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager clientAuthenticationManager; @Autowired private ClientDetailsService clientDetailsService; @Autowired private OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint; @Autowired private OAuth2AccessDeniedHandler oauthAccessDeniedHandler; @Autowired private ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter; @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { // Security rules for the token endpoint security.tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()") .authenticationEntryPoint(clientAuthenticationEntryPoint) .accessDeniedHandler(oauthAccessDeniedHandler); // Add client credentials filter after basic auth filter security.addTokenEndpointAuthenticationFilter(clientCredentialsTokenEndpointFilter); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { // Replace this with your actual client details (database, etc.) clients.inMemory() .withClient("your-client-id") .secret("{noop}your-client-secret") // Use password encoder in production .authorizedGrantTypes("password", "refresh_token") .scopes("read", "write") .authorities("ROLE_CLIENT"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(clientAuthenticationManager) .tokenStore(tokenStore()) .tokenServices(tokenServices()) .userApprovalHandler(userApprovalHandler()); } // Maps to `tokenStore` @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); // Replace with JdbcTokenStore or JwtTokenStore in production } // Maps to `tokenServices` @Bean public DefaultTokenServices tokenServices() { DefaultTokenServices tokenServices = new DefaultTokenServices(); tokenServices.setTokenStore(tokenStore()); tokenServices.setSupportRefreshToken(true); tokenServices.setAccessTokenValiditySeconds(1000); tokenServices.setClientDetailsService(clientDetailsService); return tokenServices; } // Maps to `userApprovalHandler` (completed the partial XML definition) @Bean public UserApprovalHandler userApprovalHandler() { TokenServicesUserApprovalHandler handler = new TokenServicesUserApprovalHandler(); handler.setTokenServices(tokenServices()); handler.setClientDetailsService(clientDetailsService); return handler; } }
4. Resource Server Configuration
This class secures your /api/** endpoints, using @EnableResourceServer:
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint; @Autowired private OAuth2AccessDeniedHandler oauthAccessDeniedHandler; @Autowired private AccessDecisionManager accessDecisionManager; @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.resourceId("test") .authenticationEntryPoint(oauthAuthenticationEntryPoint) .accessDeniedHandler(oauthAccessDeniedHandler) .accessDecisionManager(accessDecisionManager); } @Override public void configure(HttpSecurity http) throws Exception { // Security rules for API endpoints http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER) .and() .anonymous().disable() .authorizeRequests() .antMatchers("/api/**").hasRole("USER"); } }
Important Notes:
- Password Encoding: In production, replace
NoOpPasswordEncoderwith a strong encoder likeBCryptPasswordEncoder. The{noop}prefix is only for demo purposes to allow plain-text passwords. - Client Details: The in-memory client setup in
AuthorizationServerConfigis just an example. You should replace this with aClientDetailsServicethat loads clients from a database or other secure store. - Token Store:
InMemoryTokenStoreis fine for testing, but useJdbcTokenStore(database-backed) orJwtTokenStore(stateless JWT tokens) in production.
内容的提问来源于stack exchange,提问作者dnvsp

