Безопасность Spring и многопользовательская аутентификация - PullRequest
0 голосов
/ 05 февраля 2020

Я работаю над проектом Spring Boot, который должен отслеживать пользователей. Зарегистрируйте их и, конечно же, зарегистрируйте их, и если они долго не будут ничего делать, истек срок их сеанса, а это означает, что на веб-сайте, если он слишком журнальный, вам нужно будет войти снова. Это реализовано, и на сервере есть множество асин c запросов для ускорения работы. Мой вопрос очень прост, разрешает ли Spring Security многопользовательскую аутентификацию? Это значит, что на разных машинах одновременно могут войти в систему и общаться с сервером 50 пользователей?

Это то, что я сделал до сих пор:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService service;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/login", "/register").permitAll().anyRequest().authenticated();
        http.addFilterBefore(new AuthenticationFilter("/login", super.authenticationManagerBean()), BasicAuthenticationFilter.class)
            .addFilterBefore(new RegistrationFilter("/register", service), BasicAuthenticationFilter.class)
            .addFilterBefore(new DefaultAuthenticationToken(), BasicAuthenticationFilter.class);
    }

    private static void addResponseToken(Authentication auth, HttpServletResponse response) {
        Map<String, Object> claims = new HashMap<>();
        String token = Jwts.builder().setClaims(claims).setSubject("").setIssuedAt(new Date(System.currentTimeMillis())).setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)).signWith(SignatureAlgorithm.HS256, "").compact();
        if(response.containsHeader("Authorization"))
            response.setHeader("Authorization", token);
        else
            response.addHeader("Authorization", token);
    }

    private static class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {

        private final AuthenticationManager manager;

        protected AuthenticationFilter(String defaultFilterProcessesUrl, AuthenticationManager auth) {
            super(defaultFilterProcessesUrl);
            this.manager = auth;
        }

        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
                throws AuthenticationException, IOException {
            CredentialsDTO user = new Gson().fromJson(new InputStreamReader(request.getInputStream()), CredentialsDTO.class);
            //ObjectMapper().readValue(request.getInputStream(), UserDTO.class);
            Authentication auth = manager.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()));
            if(auth.isAuthenticated()) {
                SecurityContextHolder.getContext().setAuthentication(auth);
                return auth;
            }
            return null;
        }

        @Override
        protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                FilterChain chain, Authentication authResult) throws IOException, ServletException {
            addResponseToken(authResult, response);
        }
    }

    private static class RegistrationFilter extends AbstractAuthenticationProcessingFilter {

        private final UserService service;

        protected RegistrationFilter(String defaultFilterProcessesUrl, UserService service) {
            super(defaultFilterProcessesUrl);
            this.service = service;
        }

        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
                throws AuthenticationException, IOException {
            UserDTO user = new Gson().fromJson(new InputStreamReader(request.getInputStream()), UserDTO.class);
            //service.addUser(Transposers.toDAO(user));
            Authentication auth = new AuthToken(user.getEmail(), Arrays.asList(user.getRoles()));
            SecurityContextHolder.getContext().setAuthentication(auth);
            return auth;
        }

        @Override
        protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                FilterChain chain, Authentication authResult) throws IOException, ServletException {
            addResponseToken(authResult, response);
        }

        @Override
        protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                AuthenticationException failed) throws IOException, ServletException {

            super.unsuccessfulAuthentication(request, response, failed);
        }
    }

    private static class DefaultAuthenticationToken extends GenericFilterBean {

        @Override
        @SuppressWarnings("unchecked")
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            String input = ((HttpServletRequest) request).getHeader("Authentication");
            if(input != null && input.startsWith("Bearer ")) {
                String token = input.substring(7);
                Map<String, Object> claims = Jwts.parser().setSigningKey("").parseClaimsJws(token).getBody();
                int expiration = (int) claims.get("exp");
                if(expiration < System.currentTimeMillis() / 1000)
                    ((HttpServletResponse) request).sendError(HttpServletResponse.SC_UNAUTHORIZED);
                else {
                    List<String> roles = ((List<String>) claims.get("roles"));
                    Authentication auth = new AuthToken(claims.get("username"), roles);
                    SecurityContextHolder.getContext().setAuthentication(auth);
                    addResponseToken(auth, (HttpServletResponse) response);
                    chain.doFilter(request, response);
                }
            } else
                ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
        }

    }

    private static class AuthToken implements Authentication {

        private static final long serialVersionUID = 8528618298834061551L;
        private List<GrantedAuthority> auths;
        private String email;

        public AuthToken(Object email, List<String> asList) {
            this.email = (String) email;
            this.auths = new ArrayList<>(asList.size());
            asList.forEach((s) -> auths.add(new SimpleGrantedAuthority(s)));
        }

        @Override
        public String getName() {
            return email;
        }

        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return auths;
        }

        @Override
        public Object getCredentials() {
            return null;
        }

        @Override
        public Object getDetails() {
            return email;
        }

        @Override
        public Object getPrincipal() {
            return this;
        }

        @Override
        public boolean isAuthenticated() {
            return true;
        }

        @Override
        public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {}

    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...