Spring Security permitAll Unauthorized
Posted
技术标签:
【中文标题】Spring Security permitAll Unauthorized【英文标题】:Spring Security's permitAll Unauthorized 【发布时间】:2019-03-10 12:27:20 【问题描述】:我想忽略所有带有HttpMethod.GET
的网址,并且需要对带有 Post、Delete、Put 的网址进行身份验证。我的网址是"/api/manga","/api/grupos","/api/autor","/genero","/api/pagina","/api/capitulo"
PermitAll 不适用于 JWTFilter,如果删除过滤器,则可以正常工作。
如何忽略或允许所有带有 HttpMethod.GET
的网址?需要创建单独的 api 进行身份验证吗?
WebSecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests()
.antMatchers(HttpMethod.GET, "/api/manga", "/api/grupos", "/api/autor", "/genero", "/api/pagina",
"/api/capitulo")
.permitAll().anyRequest().fullyAuthenticated().and()
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class).httpBasic()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().csrf()
.disable();
@Override
public void configure(WebSecurity web) throws Exception
web.ignoring().antMatchers("/favicon.ico", "/", "/index.html", "/registrar", "/autenticar", "/app/**");
JWTAuthenticationFilter
public class JWTAuthenticationFilter extends GenericFilterBean
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String AUTHORITIES_KEY = "roles";
@Override
public void doFilter(final ServletRequest req, final ServletResponse res,final FilterChain filterChain)
throws IOException, ServletException
final HttpServletRequest request = (HttpServletRequest) req;
String authReader = request.getHeader(AUTHORIZATION_HEADER);
if (authReader == null || !authReader.startsWith("Bearer "))
((HttpServletResponse) res).sendError(HttpServletResponse.SC_UNAUTHORIZED, "invalido autorization");
else
try
final String token = authReader.substring(7);
final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();
request.setAttribute("claims", claims);
SecurityContextHolder.getContext().setAuthentication(getAuthentication(claims));
filterChain.doFilter(req, res);
catch (SignatureException e)
((HttpServletResponse) res).sendError(HttpServletResponse.SC_UNAUTHORIZED, "invalid token");
public Authentication getAuthentication(Claims claims)
List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
List<String> roles = (List<String>) claims.get(AUTHORITIES_KEY);
for (String role : roles)
authorities.add(new SimpleGrantedAuthority(role));
User principal = new User(claims.getSubject(), "", authorities);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToklen = new UsernamePasswordAuthenticationToken(
principal, "", authorities);
return usernamePasswordAuthenticationToklen;
控制器
@RestController
@Transactional
@RequestMapping(value="/api")
public class AutorController
@Autowired
private AutorRepository autorRepository;
@Autowired
private AutorService autorService;
@RequestMapping(value = "/autor/id", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<Page<AutorEntity>> buscarMangaPorId(@PathVariable(value = "id") Long id,
Integer page)
AutorEntity autor = autorRepository.findOne(id);
if (autor == null)
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
if (page == null)
page = 0;
if (page >= 1)
page--;
Pageable pageable = new PageRequest(page, 20);
return new ResponseEntity<>(autorService.buscarMangaPorId(id, pageable), HttpStatus.OK);
@RequestMapping(value = "/autor/lista", method = RequestMethod.GET)
public List<AutorEntity> listarAutores()
return autorService.listarTodos();
@PreAuthorize("hasAuthority('ADMIN')")
@RequestMapping(value = "/autor", method = RequestMethod.POST)
public ResponseEntity<AutorEntity> cadastrarAutor(@RequestBody AutorEntity autor)
if (autorRepository.findOneByNome(autor.getNome()) != null)
throw new RuntimeException("Nome Repetido");
return new ResponseEntity<>(autorService.cadastrar(autor), HttpStatus.OK);
如果我需要创建不同的 api 来分隔 HttpMethod,我现在不需要。
如何解决这个问题?
【问题讨论】:
.antMatchers(HttpMethod.GET) 足以允许所有 get 方法,我在 antMatchers 中使用 Method 和 URL 的组合遇到了同样的问题。如果您仍然想使用 Get 方法允许特定的 URL,我会建议这种方式 ***.com/questions/52631648/…AnonymousAuthenticationFilter
允许访问允许所有规则,它保留在UsernamePasswordAuthenticationFilter
之后。在这种情况下,您的 JWT 过滤器当然会首先被触发。首先,我建议您将安全日志级别更改为 DEBUG,您可以看到您的请求的处理顺序和过滤顺序。作为您的问题的方法,您可以使用多个 HTTP 安全配置,首先只允许所有必需的资源,其次是您的安全规则。
@saifali 我忽略了 HttpMethod.Get 并且它起作用了。 web.ignoring().antMatchers(HttpMethod.GET);
【参考方案1】:
解决方法是忽略HttpMethod.GET
,这样所有带有get方法的url都会被忽略。
@Override
public void configure(WebSecurity web) throws Exception
web.ignoring()
.antMatchers(HttpMethod.GET)
.antMatchers("/favicon.ico", "/", "/index.html", "/registrar",
"/autenticar", "/app/**");
【讨论】:
【参考方案2】:您可以提供方法类型明智的安全性,如打击。
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeRequests().antMatchers(HttpMethod.GET).permitAll();
http.authorizeRequests().antMatchers(HttpMethod.POST).denyAll();
http.authorizeRequests().antMatchers(HttpMethod.DELETE,"/url").denyAll();
http.authorizeRequests().antMatchers(HttpMethod.PATCH,"/url").denyAll();
http.authorizeRequests().antMatchers(HttpMethod.PUT,"/url/*").denyAll();
我希望它可以帮助您实现目标。
【讨论】:
无效,返回错误401 Unauthorized。我试图忽略 HttpMethot、GET 并且效果很好。web.ignoring().antMatchers (HttpMethod.GET);
以上是关于Spring Security permitAll Unauthorized的主要内容,如果未能解决你的问题,请参考以下文章
Spring Security Oauth2 permitAll()方法小记
Spring Security permitAll 不适用于某些端点
升级到 Spring Boot 2.0.2 后 Spring Security .permitAll() 不再有效
Spring Security - permitAll() 不允许未经身份验证的访问