【问题标题】:Programatically authenticate user with Spring Security 4使用 Spring Security 4 以编程方式对用户进行身份验证
【发布时间】:2016-05-11 09:37:12
【问题描述】:

我使用 inMemoryAuthentication 并且需要在访问特定端点时以编程方式对用户进行身份验证(出于测试原因)。因此我使用以下基于Programmatically login in a user using spring security的方法:

private void login(Role role) {
    logger.warn("Login User with role: " + role.toString());
    Authentication auth =
        new UsernamePasswordAuthenticationToken("user", "password", getAuthorities(role));
    SecurityContext securityContext = SecurityContextHolder.getContext();
    securityContext.setAuthentication(auth);
}

private Collection<GrantedAuthority> getAuthorities(Role role) {
    Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
    GrantedAuthority grantedAuthority = (GrantedAuthority) () -> role.toString();
    grantedAuthorities.add(grantedAuthority);
    return grantedAuthorities;
}

securityContext 设置正确(getAuthentication 按预期返回用户),但是,JSESSIONID cookie 未设置。

【问题讨论】:

    标签: spring-mvc spring-security


    【解决方案1】:

    我可以解决我的问题,但这并不容易,我不确定是否有更好的解决方案。

    我创建了一个过滤器、一个自定义 authenticationProvider 和一个自定义 authenticationToken

    public class E2EAuthenticationFilter extends GenericFilterBean {
        private final Logger logger = LoggerFactory.getLogger(E2EAuthenticationFilter.class);
    
        private AuthenticationManager authenticationManager;
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
            Role role = null;
            String username = null;
            String password = null;
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
    
            if(isLoginRequest(request.getRequestURI())){
                String roleName = getRoleName(request.getRequestURI());
                switch(roleName.toUpperCase()){
                    case "ADMIN":
                        role = Role.ADMIN;
                        username = "admin";
                        password = "admin";
                        break;
                    case "REPORTER":
                        role = Role.REPORTER;
                        username = "reporter";
                        password = "reporter";
                        break;
                    default:
                        break;
                }
    
                authenticateUser(username, password, role);
            }
    
            chain.doFilter(request, response);
        }
    
        public AuthenticationManager getAuthenticationManager() {
            return authenticationManager;
        }
    
        public void setAuthenticationManager(AuthenticationManager authenticationManager) {
            this.authenticationManager = authenticationManager;
        }
    
        private Collection<GrantedAuthority> getAuthorities(Role role) {
            Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
            GrantedAuthority grantedAuthority = (GrantedAuthority) () -> "ROLE_"+role.toString();
            grantedAuthorities.add(grantedAuthority);
            return grantedAuthorities;
        }
    
        private String getRoleName(String uri){
            String[] requestUriParts = uri.split("/");
            return requestUriParts[requestUriParts.length-1];
        }
    
        private void authenticateUser(String username, String password, Role role){
            E2EAuthenticationToken token = new E2EAuthenticationToken(username, password, getAuthorities(role));
            Authentication authResult = authenticationManager.authenticate(token);
            SecurityContextHolder.getContext().setAuthentication(authResult);
        }
    
        private boolean isLoginRequest(String uri) {
            return uri.matches("\\/e2e\\/auth\\/login\\/(\\w)+");
        }
    }
    

    authProvider 类:

    @Component
    public class E2EAuthenticationProvider implements AuthenticationProvider {
    
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            E2EAuthenticationToken token = (E2EAuthenticationToken) authentication;
            E2EAuthenticationToken authenticated = new E2EAuthenticationToken(token.getUsername(), token.getPassword(), token.getAuthorities());
    
            authenticated.setAuthenticated(true);
            return  authenticated;
        }
    
        @Override
        public boolean supports(Class<?> authentication) {
            return authentication.equals(E2EAuthenticationToken.class);
        }
    }
    

    令牌类:

    public class E2EAuthenticationToken extends AbstractAuthenticationToken {
        private String username;
        private String password;
    
        public E2EAuthenticationToken(String username, String password, Collection<? extends GrantedAuthority> authorities) {
            super(authorities);
            this.username = username;
        }
    
        @Override
        public Object getCredentials() {
            return this.username;
        }
    
        @Override
        public Object getPrincipal() {
            return this.username;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    

    最后是spring配置:

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class InMemorySecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private E2EAuthenticationProvider e2eAuthenticationProvider;
    
        @Bean
        public E2EAuthenticationFilter e2eAuthenticationFilter() throws Exception {
            E2EAuthenticationFilter filter = new E2EAuthenticationFilter();
            filter.setAuthenticationManager( authenticationManager() );
            return filter;
        }
    
        @Override
        public void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(e2eAuthenticationProvider);
    
            auth.inMemoryAuthentication()
                .withUser("admin")
                .password("admin")
                .roles(Role.ADMIN.name())
                .and()
                .withUser("reporter")
                .password("reporter")
                .roles(Role.REPORTER.name());
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .requestMatchers().antMatchers("/api/**", "/e2e/auth/**", "/acuator/**")
                .and().addFilterBefore(e2eAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("/actuator/health").permitAll()
                .antMatchers("/actuator/info").permitAll()
                .anyRequest().authenticated()
                .and().httpBasic()
                .and().csrf().disable();
        }
    }
    

    您可能已经注意到,我将此代码用于端点(当然,它仅在 E2E 配置中可用)以登录用户进行 selenium 测试。

    【讨论】:

      猜你喜欢
      • 2013-08-03
      • 1970-01-01
      • 2020-04-16
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 2012-11-27
      相关资源
      最近更新 更多