我试图创建一个安全的spring rest api的安全我想使用不透明的令牌存储在数据库中,以便如果客户端查询api上的一个承载令牌。服务器将检查数据库上的令牌是否存在,如果令牌是有效的,并获得用户和特权,并检查用户是否有权限做的请求。我已经做了一些研究,在网上,但没有“我找到了这两种方法,但我不知道在哪里也实现了数据库验证和确认。
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; } }
1条答案
按热度按时间ar7v8xwq1#
经过大量的研究,我发现这一点,它是工作的第一,我已经创建了一个授权过滤器,像这样:
和用户名密码身份验证筛选器,如下所示
如果连接成功,则生成如下标记:
然后我配置了filterChain bean,如下所示