【问题标题】:Spring token security with credential security (springboot)具有凭证安全性的 Spring 令牌安全性 (springboot)
【发布时间】:2017-11-03 07:30:20
【问题描述】:

我对服务器上的安全实施有疑问。我正在制作一个 SpringBoot 应用程序,它上面有一个类似网站的控制面板,其中 1 个管理员输入需要的数据,我设法像这样保护该部分:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {




  @Override
  protected void configure(HttpSecurity http) throws Exception {


      http.antMatcher("/*").authorizeRequests().anyRequest().hasRole("ADMIN")
        .and().formLogin().loginPage("/login.jsp")
        .failureUrl("/login.jsp?error=1").loginProcessingUrl("/login")
        .permitAll().and().logout()
        .logoutSuccessUrl("/login.jsp");

  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // Create a default account
    auth.inMemoryAuthentication()
        .withUser("admin")
        .password("admin")
        .roles("ADMIN");
  }

每个网站的 url 都在 /* 上,这很好用。我需要做的下一件事是从我的移动应用程序中检索数据,并且它需要是安全的。应用程序应该使用的 url 是 /rest/**。我有一个学生类,它存储由该管理员在网站上创建的电子邮件(用户名)和密码。据我所知,我需要令牌实现。

如何实现令牌认证?

【问题讨论】:

    标签: java spring security spring-security


    【解决方案1】:

    使用 Spring Boot 和 Spring Security 为移动应用实现基于令牌的身份验证。

    创建一个 TokenAuthenticationFilter

    public class TokenAuthenticationFilter extends GenericFilterBean {
    
        private AuthenticationManager authenticationManager;
    
        public TokenAuthenticationFilter(AuthenticationManager authenticationManager) {
            this.authenticationManager = authenticationManager;
        }
    
        @Override
        public void doFilter(ServletRequest request,
                                                 ServletResponse response,
                                                 FilterChain chain) throws IOException, ServletException {
    
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            HttpServletResponse httpResponse = (HttpServletResponse) response;
    
            String apiKey = httpRequest.getHeader("API-Key");
            String token = httpRequest.getHeader("Access-Token");
    
            try {
                if (!StringUtils.isEmpty(apiKey)) {
                    processTokenAuthentication(apiKey);
                }
                chain.doFilter(request, response);
            } catch (InternalAuthenticationServiceException internalAuthenticationServiceException)
            {
                SecurityContextHolder.clearContext();
                logger.error("Internal authentication service exception", internalAuthenticationServiceException);
                httpResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
                catch(AuthenticationException authenticationException)
            {
                SecurityContextHolder.clearContext();
                httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
            }
        }
    
        private void processTokenAuthentication(String apiKey) {
            SessionCredentials authCredentials = new SessionCredentials(apiKey);
            Authentication requestAuthentication = new PreAuthenticatedAuthenticationToken(authCredentials, authCredentials);
            Authentication resultOfAuthentication = tryToAuthenticate(requestAuthentication);
            SecurityContextHolder.getContext().setAuthentication(resultOfAuthentication);
        }
    
        private Authentication tryToAuthenticate(Authentication requestAuthentication) {
            Authentication responseAuthentication = authenticationManager.authenticate(requestAuthentication);
            if (responseAuthentication == null || !responseAuthentication.isAuthenticated()) {
                throw new InternalAuthenticationServiceException("Unable to authenticate Domain User for provided credentials");
            }
            return responseAuthentication;
        }
    }
    
    public class TokenAuthenticationProvider implements AuthenticationProvider {
    
        private String apiKey;
    
        public TokenAuthenticationProvider(String apiKey) {
            this.apiKey = apiKey;
        }
    
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            SessionCredentials credentials = (SessionCredentials) authentication.getCredentials();
            if (credentials != null && credentials.apiKey.equals(this.apiKey)) {
    
                //Also evaluate the token here
    
                Authentication newAuthentication = new PreAuthenticatedAuthenticationToken(apiKey, credentials);
                newAuthentication.setAuthenticated(true);
                return newAuthentication;
            }
            throw new BadCredentialsException("Bad credentials given.");
        }
    
        @Override
        public boolean supports(Class<?> aClass) {
            return aClass.equals(PreAuthenticatedAuthenticationToken.class);
        }
    }
    

    创建会话凭证持有者

    public class SessionCredentials {
    
        String apiKey;
        String accessToken;
    
        public SessionCredentials(String apiKey, String accessToken) {
            this.apiKey = apiKey;
            this.accessToken = accessToken;
        }
    
        public String getApiKey() {
            return apiKey;
        }
    
        public String getAccessToken() {
            return accessToken;
        }
    }
    

    最后在您的安全配置中注册这些

    //Leave whatever you had here
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new TokenAuthenticationFilter(authenticationManager()), BasicAuthenticationFilter.class);
    
        String contentPathDir = String.format("/%s/**", contentPath);
    
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests()
                .antMatchers("/authorization/**", "/public/**", "/management/**", "/health/**", contentPathDir).permitAll()
                .antMatchers("/**").authenticated();
    }
    
    
    
    
    //Add these two below. 
    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(apiKeyAuthenticationProvider());
    }
    
    @Bean
    public TokenAuthenticationProvider apiKeyAuthenticationProvider() {
        return new TokenAuthenticationProvider(apiKey);
    }
    

    【讨论】:

    猜你喜欢
    • 2019-08-31
    • 2019-02-05
    • 2018-02-08
    • 2021-01-26
    • 2011-10-29
    • 1970-01-01
    • 2016-01-20
    • 2016-03-22
    • 2018-07-31
    相关资源
    最近更新 更多