为什么不通过以下配置提示登录?当我尝试访问 / public / user 时,我收到错误403(访问被拒绝)。但是,如果我在WebServiceSecurityConfiguration.configure
取消注释这些注释行,我会根据需要重定向到登录页面。为什么要正确配置登录时需要这些行,因为antMatcher首先匹配不同的路径。我想有一些冲突,错误配置AuthenticationEntryPoint
,但我真的不知道这是怎么回事。我想要实现的是配置两个安全链,一个用于登录路径以获取JWT令牌,另一个用于Web服务以针对令牌进行身份验证。一切都与那些没有注释的线条完美配合,但我偶然注意到形式 - 登录在没有它们的情况下停止工作,并且我很困惑为什么会这样。
@Configuration
@Profile("javasecurity")
@Order(11)
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private TokenHandler tokenHandler;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password("password").authorities(new SimpleGrantedAuthority("ROLE_USER")).and()
.withUser("admin").password("password").authorities(
new SimpleGrantedAuthority("ROLE_USER"),
new SimpleGrantedAuthority("ROLE_ADMIN")).and()
.withUser("guest").password("guest").authorities(new SimpleGrantedAuthority("ROLE_GUEST"));
}
@Override
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**")
.permitAll()
.and()
.formLogin()
.successHandler(authenticationSuccessHandler())
.and()
.logout();
}
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return new AuthenticationSuccessHandler() {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
tokenHandler.setToken(response, authentication.getName());
response.getWriter().println("User authenticated and cookie sent");
response.flushBuffer();
}
};
}
@Configuration
@Profile("javasecurity")
@Order(10)
public static class WebServiceSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private TestAuthenticationFilter testAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/secured/**")
.authenticated();
// .and()
// .antMatcher("/secured/**")
// .securityContext().securityContextRepository(new NullSecurityContextRepository())
// .and()
// .addFilterAt(testAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
-
@Component("TestAuthenticationFilter")
public class TestAuthenticationFilter extends GenericFilterBean {
@Autowired
private TokenHandler tokenHandler;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("TestAuthenticationFilter doFitler");
attemptAuthentication((HttpServletRequest) request);
chain.doFilter(request, response);
clearAuthentication();
System.out.println("doFitler end");
}
public void attemptAuthentication(HttpServletRequest request) {
try {
UserDetails user = tokenHandler.loadUserFromToken(request);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, user.getPassword());
SecurityContextHolder.getContext().setAuthentication(auth);
} catch (Exception e) {
// Do nothing
}
}
public void clearAuthentication() {
SecurityContextHolder.getContext().setAuthentication(null);
}
@Configuration
public static class DisableFilterRegistration {
@Autowired
private TestAuthenticationFilter filter;
@Bean
public FilterRegistrationBean disablerBean() {
FilterRegistrationBean bean = new FilterRegistrationBean(filter);
bean.setEnabled(false);
return bean;
}
}
}
-
@Component("TokenHandler")
public class TokenHandler {
@Autowired(required = false)
private UserDetailsService userDetailsService;
public void setToken(HttpServletResponse response, String username) {
response.addCookie(new Cookie("user", username));
}
public UserDetails loadUserFromToken(HttpServletRequest request) throws BadCredentialsException {
Cookie[] cookies = request.getCookies();
Cookie token = null;
for (Cookie c : cookies) {
if (c.getName().equals("user")) {
token = c;
break;
}
}
if (token == null)
return null;
else
return userDetailsService.loadUserByUsername(token.getValue());
}
}
-
@RestController
@RequestMapping("/public")
public class PublicController {
@GetMapping("/norole")
public String noRole() {
return "no role";
}
@GetMapping("/user")
@PreAuthorize("hasRole('ROLE_USER')")
public String roleUser() {
return "role_user";
}
}
-
@RestController
@RequestMapping("/secured")
public class SecuredController {
@GetMapping("/user")
@PreAuthorize("hasRole('ROLE_USER')")
public String roleUser() {
return "role_user";
}
@GetMapping("/admin")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String roleAdmin() {
return "role_admin";
}
@GetMapping("/norole")
public String noRole() {
return "no role";
}
}
答案 0 :(得分:-1)
在声明添加
后,登录功能再次起作用http.antMatcher("/secured/**")
作为WebServiceSecurityConfiguration.configure
中的第一个电话。这是否意味着如果没有它,配置会否定表单登录,在此特定配置之后配置?此外,似乎antMatcher
的位置可以是任意的,是这种情况吗?有人可以解释那里发生的事情吗?