spring - 在基于 Spring Security 角色的身份验证和授权中获取 Forbidden 错误
问题描述
我正在尝试学习 Spring 安全性,但我遇到了基于角色的安全性问题。
有 2 个表User和Role具有一对多的关系。
当我以 Spring 默认形式输入用户名和密码时,我通过 loadUserByUserName() 方法成功获取了正确的用户详细信息。但在屏幕上我收到一条消息
此应用程序没有显式映射 /error,因此您将其视为后备。
出现意外错误(类型=禁止,状态=403)。禁止的
只有 @GetMapping("/user") 方法可以正常工作。
这是控制器部分
@RestController
@RequestMapping("/admin")
public class AdminController {
@Autowired
UserRepository userRepo;
@Autowired
RoleRepository roleRepo;
@PreAuthorize("hasAnyRole('ADMIN')")
@PostMapping("/add")
public String addUserByAdmin(@RequestBody User user)
{
user.getRoles().forEach(role -> role.setUser(user));
userRepo.save(user);
return "User added Successfully";
}
@PreAuthorize("hasAnyRole('ADMIN')")
@GetMapping("/process")
public String process()
{
return "Processing....";
}
@GetMapping("/user")
public String users() // This code is working properly
{
System.out.println("U r in user area's");
return "User's space";
}
}
配置部分
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableJpaRepositories(basePackageClasses = UserRepository.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
protected void configure(HttpSecurity http)throws Exception
{
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().permitAll();
}
}
服务部分
@Service
public class CustomeUserDetailsService implements UserDetailsService
{
@Autowired
UserRepository userRepo;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User u = userRepo.findByName(username);
CustomeUserDetails cUserDetails = new CustomeUserDetails();
if(u == null)
{
throw new UsernameNotFoundException("User "+username +"not found");
}
else
{
cUserDetails.setUser(u);
}
return cUserDetails;
}
}
我哪里错了?
如果我想再添加一个不需要任何身份验证和授权的 URL,如何添加呢?
解决方案
我认为您应该使用“ROLE_ADMIN”而不是“ADMIN”。“ROLE_ADMIN”键可以保存在数据库中并变成Collection。下面我是怎么做的。
实现用户详细信息的类
public class UsuarioSS implements LdapUserDetails {
private static final long serialVersionUID = 1164806375870272028L;
private String cdusuariorede;
private Collection<GrantedAuthority> authorities;
public UsuarioSS() {
}
public UsuarioSS(String cdusuariorede,List<Perfil> perfis) {
super();
this.cdusuariorede = cdusuariorede;
this.authorities = new ArrayList<GrantedAuthority>();
for (Perfil perfil : perfis) {
this.authorities.add(new SimpleGrantedAuthority(perfil.toString()));
}
}
public String getId() {
return cdusuariorede;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return cdusuariorede;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public boolean hasRole(String springSecurityKey) {
return getAuthorities().contains(new SimpleGrantedAuthority(springSecurityKey));
}
@Override
public void eraseCredentials() {
// TODO Auto-generated method stub
}
@Override
public String getDn() {
// TODO Auto-generated method stub
return null;
}
}
代表我的用户配置文件的枚举(AUTHORITHYES)
public enum Perfil {
ROLE_ADMIN,ROLE_DEFAULT
}
授权过滤器
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
private JWTUtil jwtUtil;
private UserDetailsService userDetailsService;
public JWTAuthorizationFilter(AuthenticationManager authenticationManager, JWTUtil jwtUtil,
UserDetailsService userDetailsService) {
super(authenticationManager);
this.jwtUtil = jwtUtil;
this.userDetailsService = userDetailsService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String header = request.getHeader("Authorization");
if (header != null && header.startsWith("Bearer ")) {
UsernamePasswordAuthenticationToken auth = getAuthentication(header.substring(7));
if (auth != null) {
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication(String token) {
if (jwtUtil.tokenValido(token)) {
String login = jwtUtil.getLogin(token);
UserDetails usuario = userDetailsService.loadUserByUsername(login);
return new UsernamePasswordAuthenticationToken(usuario, null, usuario.getAuthorities());
}
return null;
}
}
我的控制器
@RestController
@RequestMapping(value = "/parte") 公共类 ParteController {
@Autowired
private ParteService service;
@PreAuthorize("hasAnyRole('ROLE_ADMIN')")
@GetMapping("/partes_demandadas_por_processo")
public ResponseEntity<List<TpPartesProcessoDto>> getPartesPorNuprocesso(
@RequestParam(name = "processo",required = true)
@Length(max = 15,min = 15,message = "O campo processo deve possuir 15 caracteres.")
String processo
) throws SQLException{
List<TpPartesProcessoDto> partes = service.getPartesdoProcessoPorNuprocesso(processo);
return ResponseEntity.ok().body(partes);
}
}
推荐阅读
- xamarin - “Maximum”属性的绑定值不适用于 Slider Xamarin
- javascript - 如何保持节点 api 执行直到数据库查询不返回 null
- android - 如何不将包含文件的目录添加到最终 apk
- javascript - 从 node_modules 导入的 React/Webpack Css 未正确加载
- java - Spring Boot - 在不知道 POST 请求的关键参数的情况下在控制器中获取上传的文件?
- r - 带有嵌套变量的 lme 函数的问题:(any(notIntX <- !apply(X, 2, const))
- matlab - 如何选择将一个参数的值传递给具有多个输入的 MATLAB 函数?
- r - 如何让 Beamer Rmarkdown appendixnumberbeamer 包不计算附录页数?
- javascript - 如何在 TypeScript 中键入 void 函数时的异步函数
- python - 如何计算任何字符串数组出现在 Python 文本中的次数?