Для обработки вашего вопроса мне нужен источник MyAuthenticationFilter и MyAuthenticationProvider.Но у меня есть лучшее решение, которое реализовывалось ранее, вы можете найти полностью работоспособный пример пружинной безопасности, настроенный с помощью Custom Authentication и RBAC (Role-based Access Control), на моем github, готовом для вас: https://github.com/mehditahmasebi/spring/tree/master/spring-boot
Я надеюсь, что это поможет вам.
Мой WebConfig (или, как вы сказали, AppConfig) Источники:
@Configuration
@EnableWebMvc
@EnableWebSecurity
@EnableGlobalMethodSecurity(
prePostEnabled=true,
securedEnabled=true,
jsr250Enabled=true)
public class WebConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedHeaders("*")
.allowedMethods("GET, POST, PATCH, PUT, DELETE, OPTIONS")
.allowedOrigins("*");
}
@Bean
public InternalResourceViewResolver jspViewResolver() {
InternalResourceViewResolver resolver= new InternalResourceViewResolver();
resolver.setPrefix("/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
@Bean
public ErrorPageFilter errorPageFilter() {
return new ErrorPageFilter();
}
}
и источник CustomAuthentication:
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
public CustomAuthenticationProvider() {
super();
}
// API
@Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
final String name = authentication.getName();
final String password = authentication.getCredentials().toString();
final List<GrantedAuthority> grantedAuths = new ArrayList<>();
if(!(name.equals("admin") && password.equals("admin")) &&
!(name.equals("user") && password.equals("user")))
throw new RuntimeException("username or password is incorrect");
if(name.equals("admin"))
{
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
else
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
final UserDetails principal = new User(name, password, grantedAuths);
final Authentication auth = new UsernamePasswordAuthenticationToken(principal, password, grantedAuths);
return auth;
}
@Override
public boolean supports(final Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
и источник LoginService:
@RestController
@RequestMapping("/public/login")
public class LoginService {
@Autowired
CustomAuthenticationProvider provider;
@GetMapping
public String loginTest(){
return "Login OK";
}
@GetMapping("/{username}/{password}")
public ResponseEntity<Map<String, String>> login(@PathVariable String username,@PathVariable String password ,HttpServletRequest request)
{
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication authenticate = provider.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authenticate);
request.getSession().setAttribute("username", username);
Map<String, String> result = new HashMap<>();
result.put(username, new String(Base64.getEncoder().encode(password.getBytes())));
ResponseEntity<Map<String, String>> finalResult = new ResponseEntity<>(result,HttpStatus.OK);
return finalResult;
}
}
Для запуска проекта загрузите его и запустите:
mvnw spring-boot: запустите
, а затем -> http://localhost:8080/public/login/admin/admin
тогда вы получите успешный результат, как хотите.
Приветствия.
РЕДАКТИРОВАТЬ:
После обновления вопроса с добавленным источником, я обнаружил проблему.
Есть какое-то решение:
изменить / ** на / login
http.addFilterBefore(new MyAuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/login").hasAnyRole()
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic().disable();
Или самым простым способом удалить свои antMatchers **:
http.addFilterBefore(new MyAuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic().disable();
На самом деле, если вы хотите проверить роль, не рекомендуется проверять роль в службе регистрации, лучше сначала войти в систему, а затем проверять роль следующего запроса (другого конкретного antMatcherUrl).
В то же время выможно использовать @Secured для авторизации роли.
Для обеспечения безопасности я добавил службу Hello для обеспечения безопасности исключительной ситуации до входа в систему, а после входа в систему все идет хорошо.
@RestController("/hello")
public class HelloService {
@GetMapping
public String get()
{
return "Hello there!";
}
}