我目前正在开发一个带有React前端和Spring Boot后端的fullstack web应用程序。我已经为身份验证实现了Spring Security性和JWT,但此后我无法访问APIendpoint(请参阅控制器)。我已经设法访问了GET请求endpoint,但是,尽管在启动请求之前登录了后端,但PUT或DELETE请求似乎都不起作用。
我在另一篇文章中看到禁用csrf解决了这个问题,但我从来没有启用过它,所以这对我来说不起作用。
WebSecurity配置文件:
@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/v*/registration/**")
.permitAll()
.anyRequest()
.authenticated().and()
.formLogin();
}
控制器(REST API)
@RestController
@RequestMapping(path = "/question")
@CrossOrigin("*")
public class QuestionController {
private final QuestionService questionService;
@Autowired
public QuestionController(QuestionService questionService) {
this.questionService = questionService;
}
@CrossOrigin("*")
@GetMapping("/all")
public ResponseEntity<List<Question>> getAllQuestions() {
List<Question> questions = questionService.findAllQuestions();
return new ResponseEntity<>(questions, HttpStatus.OK);
}
@CrossOrigin("*")
@GetMapping("/find/{id}")
public ResponseEntity<Question> getQuestionById(@PathVariable("id") Long id) {
Question question = questionService.findQuestionById(id);
return new ResponseEntity<>(question, HttpStatus.OK);
}
@CrossOrigin("*")
@PostMapping("/add")
public ResponseEntity<Question> addQuestion(@RequestBody Question question) {
Question newQuestion = questionService.addQuestion(question);
return new ResponseEntity<>(newQuestion, HttpStatus.CREATED);
}
@CrossOrigin("*")
@PutMapping("/update/{id}")
public ResponseEntity<Question> updateQuestion(@RequestBody Question question) {
Question updateQuestion = questionService.updateQuestion(question);
return new ResponseEntity<>(updateQuestion, HttpStatus.OK);
}
@CrossOrigin("*")
@DeleteMapping("(/delete/{id}")
public ResponseEntity<Question> deleteQuestion(@PathVariable("id") Long id) {
questionService.deleteQuestion(id);
return new ResponseEntity<>(HttpStatus.OK);
}
}
编辑:这是实现UserDetailsService的代码
@Service
@Autowired can be left out by using this annotation.
@AllArgsConstructor
public class BenutzerkontoService implements UserDetailsService {
private final static String USER_NOT_FOUND_MSG = "User with email %s not found";
private final BenutzerkontoRepository benutzerkontoRepository;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
private final ConfirmationTokenService confirmationTokenService;
public List<Benutzerkonto> findAllBenutzerkonto() {
// findAll() returns a list of all user objects
return benutzerkontoRepository.findAll();
}
/**
* This method is responsible for identifying the given email inside the database.
*
* @param email
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
return benutzerkontoRepository.findByEmail(email).orElseThrow(() -> new UsernameNotFoundException(String.format(USER_NOT_FOUND_MSG, email)));
}
/**
* The following function checks, whether the user already exists (by email) and registers the user with an
* encoded password, if the email address does not exist already.
*
* The user also gets a random JSON Web Token assigned
*
* @param benutzerkonto
* @return
*/
public String signUpUser(Benutzerkonto benutzerkonto) {
// Check whether user exists
boolean userExists = benutzerkontoRepository.findByEmail(benutzerkonto.getEmail()).isPresent();
if (userExists) {
throw new IllegalStateException("Email is already taken");
}
// Encode the user password
String encodedPassword = bCryptPasswordEncoder.encode(benutzerkonto.getPassword());
// Replace the plain text password with the encoded version
benutzerkonto.setPasswort(encodedPassword);
// Save user to database
benutzerkontoRepository.save(benutzerkonto);
// Create random String via the UUID class for using it as token
String token = UUID.randomUUID().toString();
// Instantiate ConfirmationToken class, which defines the token for account confirmation
ConfirmationToken confirmationToken = new ConfirmationToken(
token,
LocalDateTime.now(),
// Make token invalid after 15 minutes
LocalDateTime.now().plusMinutes(15),
benutzerkonto
);
// Save token to database
// TODO: Shouldn't it be saved by a confirmationTokenRepository object? Why does this also work?
confirmationTokenService.saveConfirmationToken(confirmationToken);
return token;
}
/**
* This function takes the email address as a parameter and enables/activates the email for logging in.
*
* @param email
* @return
*/
public int enableAppUser(String email) {
return benutzerkontoRepository.enableAppUser(email);
}
/**
* This method adds a new user account to the database, but it searches for the passed value of email
* inside the database first. The user object "benutzerkonto" will only be saved in the database repository,
* if the email does not exist already.
*
* @param benutzerkonto
*/
public void addNewUser(Benutzerkonto benutzerkonto) {
// userEmailPresence can be null, if the email does not exist in the database yet, which is why it's an Optional.
Optional<Benutzerkonto> userEmailPresence = benutzerkontoRepository.findBenutzerkontoByEmail(benutzerkonto.getUsername());
if (userEmailPresence.isPresent()) {
throw new IllegalStateException("Email already taken.");
} else {
benutzerkontoRepository.save(benutzerkonto);
}
}
}
因此,除了请求 /api/v*/注册/**其他都是安全的。这是什么意思?,这意味着在您拥有授权角色的授权用户之前,无法访问任何其他终结点。所以你需要做一些事情,比如:
>
实现包组织的UserDetails。springframework。安全果心userdetails并实现该方法:
@覆盖公共收藏
向实体类添加角色:
@OneTo很多(读取=FetchType.EAGER,级联=CascadeType。PERSIST)@JoinTable(name="user_role",joinColns=@JoinColiv(name="user_id",引用的列名="id"),inverseJoinColns=@JoinColiv(name="role_id",引用的列名="id"))私有列表角色;
在endpoint中使用这些角色:
@preAuthorize(hasRole('ROLE_role_name'))@GetMap(path=EndPoint.PATIENT_HOME,消耗="应用程序/json",产生="应用程序/json")公共响应实体主页(主要主体){
return new ResponseEntity<YourDTO>(yourDTO, HttpStatus.OK);
}
我尝试使用Registfit2.0来实现一个库系统。可以添加图书,列出所有图书信息,列出一本书信息,删除一本书,删除所有图书,更新一本书信息。 我的baseURL结尾有一个“/”: 前三个特性工作得很好: 您将在响应中看到,检查请求信息,method是“get”,但标记显示method=“delete”。 Update2:根据Dexter的建议,我添加了用于调试的HttpLoggingInterc
问题内容: 我有以下通常正常工作的代码: 对于我的许多实体类来说,这都是可行的。但是对于其中的两个它什么也不做,它不会引发任何异常,也不会删除该对象。来自hibernate的日志显示,hibernate执行了许多选择查询,但它甚至没有尝试执行删除。 我已经在这里和这里尝试了在其他类似问题中发现的建议,但是没有用(嗯,后者建议我不能使用,但是我只是在和之间加上了语句)。 我似乎找不到这两个类比其他类
我有以下通常运行良好的代码: 对于我的许多实体类,这很有效。但是,对于其中两个,它什么都不做,它不会引发任何异常,也不会删除对象。来自Hibernate的日志显示Hibernate执行了许多选择查询,但它甚至不会尝试执行删除。 我已经尝试了在这里和这里的其他类似问题中找到的建议,但无济于事(好吧,后者建议我不能使用,但我只是将语句括在和之间)。 我似乎找不到这两个班比其他班多(或少)什么。他们使用
我一直在阅读一篇又一篇的帖子和文章,试图让级联删除在最新的Spring Boot版本中与JPA/Hibernate配合使用。我读过你必须使用Hibernate特定的级联,我读过你不需要。我读过它们就是不起作用,但它似乎是一个混合体。我尝试过的一切都不起作用。这种关系是双向的。 不工作: 不工作: 在删除品牌之前,除了删除税率之外,还有什么其他方法有效吗? 我的测试如下所示: 参考错误: 原因:or
问题内容: 我试图通过执行以下循环来获取TreeMap的前10个元素: 该打印 工具,为什么可能不起作用? 更新 这是我的实现: 更新 这很有用:Java Map按值排序。 问题答案: public int compare(Integer a, Integer b) { if (base.get(a) >= base.get(b)) { return -1; } else { return 1;
我使用的是Kafka版本0.8.2。在开发过程中,我想我可能需要删除一个主题。所以我所做的是在服务器配置文件中放入以下一行,并启动两台kafka服务器。 当我需要删除一个主题并运行以下命令时, 现在距我运行“删除主题”命令已经17个小时了,但Kafka仍在向我显示该主题已标记为删除。是Kafka的虫子还是我在这里做错了什么?因为在我看来这不正常。有人能就此澄清一下吗?