spring-security Spring Security中的不透明令牌实现

a2mppw5e  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(166)

我试图创建一个安全的spring rest api的安全我想使用不透明的令牌存储在数据库中,以便如果客户端查询api上的一个承载令牌。服务器将检查数据库上的令牌是否存在,如果令牌是有效的,并获得用户和特权,并检查用户是否有权限做的请求。我已经做了一些研究,在网上,但没有“我找到了这两种方法,但我不知道在哪里也实现了数据库验证和确认。

ar7v8xwq

ar7v8xwq1#

经过大量的研究,我发现这一点,它是工作的第一,我已经创建了一个授权过滤器,像这样:

package com.example.bda_test_11.security;

import com.example.bda_test_11.model.BdaUser;
import com.example.bda_test_11.model.Token;
import com.example.bda_test_11.repository.TokenRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
public class AuthorizationFilter extends BasicAuthenticationFilter {
    private final TokenRepository tokenRepository;
    public AuthorizationFilter(AuthenticationManager authenticationManager,TokenRepository tokenRepository) {
        super(authenticationManager);
        this.tokenRepository = tokenRepository;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String tokenCode = request.getHeader(HttpHeaders.AUTHORIZATION);
        log.info(tokenCode);
        if(tokenCode == null ) {
            filterChain.doFilter(request,response);
            return;
        }
        Token token = tokenRepository.findByCode(tokenCode).orElse(null);
        if (token == null) {

            filterChain.doFilter(request,response);
            return;
        }
        BdaUser user = token.getUser();
        UsernamePasswordAuthenticationToken userToken = new UsernamePasswordAuthenticationToken(user.getLogin(),null,user.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(userToken);
        filterChain.doFilter(request,response);
    }
}

和用户名密码身份验证筛选器,如下所示

package com.example.bda_test_11.security;

import com.example.bda_test_11.security.domain.LoginCredentials;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@Slf4j
public class JsonObjectAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
        try{

            BufferedReader reader = request.getReader();
            StringBuilder stringBuilder = new StringBuilder();
            String line;
            while ((line=reader.readLine())!=null){
                stringBuilder.append(line);
            }
            LoginCredentials authRequest = objectMapper.readValue(stringBuilder.toString(),LoginCredentials.class);
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
                    authRequest.getLogin(),
                    authRequest.getPassword()
            );
            setDetails(request,token);
            log.info(token.toString());
            return this.getAuthenticationManager().authenticate(token);
        } catch (IOException e){
            throw new RuntimeException(e);
        }
    }
}

如果连接成功,则生成如下标记:

package com.example.bda_test_11.security;

import com.example.bda_test_11.model.BdaUser;
import com.example.bda_test_11.model.Token;
import com.example.bda_test_11.repository.TokenRepository;
import com.example.bda_test_11.service.BdaUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j @Component
public class AuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    private final TokenRepository tokenRepository;
    private final BdaUserService userService;

    @Autowired
    public AuthSuccessHandler(TokenRepository tokenRepository, BdaUserService userService) {
        this.tokenRepository = tokenRepository;
        this.userService = userService;
    }
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        UserDetails principal = (UserDetails) authentication.getPrincipal();
        BdaUser user = userService.findByLogin(principal.getUsername());
        Token token = new Token(user);
        tokenRepository.save(token);
        log.info(token.getCode());
        response.addHeader("Authorization",token.getCode());
        response.addHeader("Content-Type","application/json");
        response.getWriter().write("{\"token\":"+token.getCode()+",\"login\":"+user.getLogin());
    }
}

然后我配置了filterChain bean,如下所示

package com.example.bda_test_11.security;

import com.example.bda_test_11.repository.TokenRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;

@Configuration
public class BdaSecurity {
    private final AuthenticationManager authenticationManager;
    private final AuthSuccessHandler authSuccessHandler;
    private final TokenRepository tokenRepository;

    @Autowired
    public BdaSecurity(AuthenticationManager authenticationManager, AuthSuccessHandler authSuccessHandler, TokenRepository tokenRepository) {
        this.authenticationManager = authenticationManager;
        this.authSuccessHandler = authSuccessHandler;
        this.tokenRepository = tokenRepository;
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf()
                .disable()
                .authorizeHttpRequests((auth)->{

                    try {
                        auth
                                .antMatchers("/api/admin").hasAuthority("ADMIN")
                                .antMatchers("/api/user").hasAuthority("USER")
                                .anyRequest().permitAll()
                                .and()
                                .sessionManagement()
                                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                                .and()
                                .addFilter(authenticationFilter())
                                .addFilter(new AuthorizationFilter(authenticationManager,tokenRepository))
                                .exceptionHandling()
                                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                })
                .httpBasic(Customizer.withDefaults());
        return http.build();
    }
    @Bean
    public JsonObjectAuthenticationFilter authenticationFilter() {
        JsonObjectAuthenticationFilter filter = new JsonObjectAuthenticationFilter();
        filter.setAuthenticationSuccessHandler(authSuccessHandler);
        filter.setAuthenticationManager(authenticationManager);
        return filter;
    }
}

相关问题