简体   繁体   English

Spring Security Java配置混乱

[英]Spring Security java configuration confusion

Why the login isn't prompted with following configuration? 为什么以下配置没有提示登录? When I try to access /public/user , I get error 403 (access denied). 当我尝试访问/ public / user时 ,出现错误403(访问被拒绝)。 However, if I uncomment those commented lines at WebServiceSecurityConfiguration.configure , I got redirected to login page, as desired. 但是,如果我取消注释WebServiceSecurityConfiguration.configure注释行,则会根据需要将我重定向到登录页面。 Why those lines are needed for from-login being properly configured, as the antMatcher matches different path in the first place. 为什么antMatcher首先匹配不同的路径,所以正确配置from-log需要这些行。 I guess there is some conflict, which misconfigures the AuthenticationEntryPoint , but I don't really have idea how that happens. 我猜这里有一些冲突,错误地配置了AuthenticationEntryPoint ,但是我真的不知道该如何发生。 What I'm trying to achieve is configuring two security chains, one for login path to obtain the JWT token, and another for web services to authenticate against the token. 我要实现的目标是配置两个安全链,一个安全链用于登录路径以获得JWT令牌,另一个安全链用于Web服务针对该令牌进行身份验证。 Everything works perfectly with those lines uncommented, but I noticed by accident form-login stopped working without them, and am super confused why is that. 在没有注释的情况下,一切都可以正常运行,但是我偶然地注意到,没有它们,表单登录就停止了工作,对此感到非常困惑。

@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";
    }
}

Login-from got functional again after declaring adding 声明添加后,登录源再次起作用

http.antMatcher("/secured/**")

As the first call in the WebServiceSecurityConfiguration.configure . 作为WebServiceSecurityConfiguration.configure的第一个调用。 Does that mean that without it the configuration negates the form-login, which is configured after this particular configuration? 这是否意味着没有它,配置将否定此特定配置之后配置的表单登录? Also, it seems like the position of antMatcher can be arbitrary, is this the case? 另外,似乎antMatcher的位置可以是任意的,是这种情况吗? Could someone explain what is actually happening there? 有人可以解释一下那里到底发生了什么吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM