SME*_*SME 11 spring spring-security spring-boot
我有一个创建了一个包含这个方法的类JwtAuthenticationFilter:
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
Authentication authentication = null;
if(hasJsonToken(request)) {
JwtAuthenticationToken jwtAuthenticationToken = new JwtAuthenticationToken(getJsonToken(request));
authentication = getAuthenticationManager().authenticate(jwtAuthenticationToken);
} else {
throw new AuthenticationCredentialsNotFoundException(AUTHENTICATION_CREDENTIALS_NOT_FOUND_MSG);
}
return authentication;
}
Run Code Online (Sandbox Code Playgroud)
如果未提供JWT,则抛出AuthenticationCredentialsNotFoundException.我希望这会在我的AuthenticationEntryPoint中触发begin方法 - 看起来像这样:
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpStatus.UNAUTHORIZED.value(),HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
Run Code Online (Sandbox Code Playgroud)
开始方法没有被调用.这在我的spring安全配置(或其中的一部分)中:
@Bean
public RestAuthenticationEntryPoint restAuthenticationEntryPoint() {
return new RestAuthenticationEntryPoint();
}
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint()).and()
.csrf().disable()
.authorizeRequests().antMatchers(AUTHORISED_SERVICE_REQUESTS_ANT_MATCHER).authenticated()
.anyRequest().permitAll();
}
Run Code Online (Sandbox Code Playgroud)
我不确定这里有什么错误,我希望有人指出我.谢谢
我的SecurityConfig类扩展了WebSecurityConfigurerAdapter,并使用@Configuration和@EnableWebSecurity进行了注释.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}
Run Code Online (Sandbox Code Playgroud)
我正在使用弹簧靴.
所以...最终我通过创建自定义AuthenticationFailureHandler并在我的Authentication F.ilter中注册它来获得我想要的行为
jwtAuthenticationFilter.setAuthenticationFailureHandler(new JwtAuthenticationFailureHandler());
Run Code Online (Sandbox Code Playgroud)
我现在的问题是,这是正确的做法,AuthenticationEntryPoint和AuthenticationFailureHandler有什么区别?
小智 10
这是我使用 Spring Boot / JWT 实现 AuthenticationEntryPoint 和 AccessDeniedHandler 的代码。我希望它对任何人都有帮助。
认证入口点
@Component
public class AuthenticationEntryPointJwt implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException authenticationException) throws IOException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final Map<String, Object> body = new HashMap<>();
body.put("code", HttpServletResponse.SC_UNAUTHORIZED);
body.put("payload", "You need to login first in order to perform this action.");
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(httpServletResponse.getOutputStream(), body);
}
}
Run Code Online (Sandbox Code Playgroud)
拒绝访问处理程序
@Component
public class AccessDeniedHandlerJwt implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
final Map<String, Object> body = new HashMap<>();
body.put("code", HttpServletResponse.SC_FORBIDDEN);
body.put("payload", "You don't have required role to perform this action.");
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(httpServletResponse.getOutputStream(), body);
}
}
Run Code Online (Sandbox Code Playgroud)
Web安全配置适配器
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private Environment env;
@Autowired
private SecurityUserDetailsService securityUserDetailsService;
@Autowired
private SecurityRequestFilter securityRequestFilter;
@Autowired
private AuthenticationEntryPointJwt authenticationEntryPointJwt;
@Autowired
private AccessDeniedHandlerJwt accessDeniedHandlerJwt;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(securityUserDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
if (Boolean.parseBoolean(env.getRequiredProperty("security.disable.csrf")))
httpSecurity.csrf().disable();
httpSecurity
.httpBasic().disable()
.formLogin().disable()
.authorizeRequests()
.antMatchers(env.getRequiredProperty("security.uri.white-list").split(",")).permitAll()
.anyRequest().authenticated().and()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPointJwt).and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandlerJwt).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(securityRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
Run Code Online (Sandbox Code Playgroud)
你可以在我的GitHub上查看完整的代码
AuthenticationEntryPoint和之间的区别在于AuthenticationFailureHandler前者用于“告诉”未经身份验证的用户在哪里进行身份验证,例如,通过将他们重定向到登录表单。后者用于处理错误的登录尝试。
你AuthenticationEntryPoint很可能没有被调用,因为你抛出了一个异常。如果用户尝试访问需要身份验证的端点并且您没有抛出任何内容,则会调用它。在不存在凭据的情况下,不需要对用户进行身份验证就足够了,您不需要抛出异常。
如果您正在创建使用 JWT 身份验证的应用程序,您可能不想将用户重定向到任何地方,因此您只需使用org.springframework.security.web.authentication.HttpStatusEntryPoint或 像您这样的入口点来返回状态代码。
| 归档时间: |
|
| 查看次数: |
3222 次 |
| 最近记录: |