Я новичок в весенней загрузке и пытаюсь защитить свое приложение.
Я сделаю следующее:
Маршрут "/ api / " должен быть защищен маркером доступа с oauth, а маршруты "/ user / " - обычным логином Basic-Auth Form.
Для этого у меня реализованы следующие классы
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Configuration
@Order(2)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${security.signing-key}")
private String signingKey;
@Value("${security.encoding-strength}")
private Integer encodingStrength;
@Value("${security.security-realm}")
private String securityRealm;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/api/**").hasRole("admin").and().httpBasic()
.authenticationEntryPoint(authenticationEntryPoint());
}
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint();
entryPoint.setRealmName(securityRealm);
return entryPoint;
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(signingKey);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
}
@Configuration
@Order(1)
public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String LOGIN_PROCESSING_URL = "/login";
private static final String LOGIN_FAILURE_URL = "/login?error";
private static final String LOGIN_URL = "/login";
private static final String LOGOUT_SUCCESS_URL = "/logout";
private static final String LOGIN_SUCCESS_URL = "/user";
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/user").hasAnyAuthority(Role.getAllRoles()).anyRequest().authenticated().and()
.formLogin().loginPage("/login").permitAll().and()
.logout().permitAll();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
//...)
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public User currentUser(UserRepository userRepository) {
return userRepository.findByEmailIgnoreCase(SecurityUtils.getUsername());
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
super.configure(auth);
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
@Bean()
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
}
и
@Service
@Primary
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByEmailIgnoreCase(username);
if (null == user) {
throw new UsernameNotFoundException("No user present with username: " + username);
} else {
List<GrantedAuthority> auths = new ArrayList<>();
for(Role role: user.getRoles()) {
auths.add(new SimpleGrantedAuthority(role.getName()));
}
Collection<? extends GrantedAuthority> authorities = auths;
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPasswordHash(),
authorities);
}
}
}
и
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Value("${security.jwt.client-id}")
private String clientId;
@Value("${security.jwt.client-secret}")
private String clientSecret;
@Value("${security.jwt.grant-type}")
private String grantType;
@Value("${security.jwt.scope-read}")
private String scopeRead;
@Value("${security.jwt.scope-write}")
private String scopeWrite = "write";
@Value("${security.jwt.resource-ids}")
private String resourceIds;
@Autowired
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
endpoints.tokenStore(tokenStore)
.accessTokenConverter(accessTokenConverter)
.tokenEnhancer(enhancerChain)
.authenticationManager(authenticationManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(clientId)
.secret(passwordEncoder.encode(clientSecret))
.authorizedGrantTypes(grantType)
.scopes(scopeRead, scopeWrite)
.resourceIds(resourceIds);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
}
и
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private ResourceServerTokenServices tokenServices;
@Value("${security.jwt.resource-ids}")
private String resourceIds;
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().and().authorizeRequests()
.antMatchers("/oauth/token").permitAll().antMatchers("/api/**").authenticated();
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(resourceIds).tokenServices(tokenServices);
}
}
Путь "/ user" защищен входом в систему, но ресурс / api / test-Resource также защищен обычной формой входа. В / oauth / token я получаю токен доступа после запроса, как хочу.
Но как я могу сконфигурировать мои классы конфигурации, чтобы / api / ** был защищен токеном? И где я должен настроить пути, в WebSecurityConfig или в ResourceServerConfig? С сегодняшнего дня спички в обоих классах. Я не нашел хорошего учебника для своей особой Задачи.