Spring Boot 返回错误:不支持内容类型 ‘text/plain;charset=UTF-8’。

huangapple go评论114阅读模式
英文:

Spring Boot returning error Content type 'text/plain;charset=UTF-8' not supported

问题

我尝试从我的JavaScript文件向本地主机的服务器发送POST请求,以验证登录。

这是我的前端代码:

HTML

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>WorkSoftManager - 登录</title>
  6. <link rel="stylesheet" type="text/css" href="styleLogin.css">
  7. </head>
  8. <body>
  9. <div class="container">
  10. <h1>WorkSoftManager</h1>
  11. <h2>登录</h2>
  12. <form id="login-form">
  13. <input type="email" id="username" placeholder="电子邮件" required>
  14. <input type="password" id="password" placeholder="密码" required>
  15. <button type="submit">登录</button>
  16. </form>
  17. <p>没有账户?<a href="signUp.html">注册</a></p>
  18. </div>
  19. <script src="script.js"></script>
  20. </body>
  21. </html>

JavaScript

  1. // 创建处理登录过程的函数
  2. async function login(username, password) {
  3. try {
  4. const response = await fetch('http://localhost:8080/api/login/', {
  5. method: 'POST',
  6. mode: 'no-cors',
  7. headers: {
  8. 'Content-Type': 'application/json'
  9. },
  10. body: JSON.stringify({
  11. 'username': username,
  12. 'password': password
  13. })
  14. });
  15. // 检查响应是否成功
  16. if (!response.ok) {
  17. throw new Error('登录失败。请重试。');
  18. }
  19. // 解析响应的JSON数据
  20. const data = await response.json();
  21. // 检查身份验证是否成功
  22. if (!data.authenticated) {
  23. throw an Error('无效的用户名或密码。');
  24. }
  25. // 将身份验证令牌存储在本地存储中
  26. localStorage.setItem('token', data.token);
  27. // 重定向用户到loginPage.html页面
  28. window.location.href = '/loginPage.html';
  29. } catch (error) {
  30. // 显示错误消息
  31. alert(error.message);
  32. }
  33. }
  34. // 附加事件侦听器到登录表单的提交按钮
  35. document.getElementById('login-form').addEventListener('submit', (event) => {
  36. event.preventDefault();
  37. // 获取用户名和密码输入的值
  38. const username = document.getElementById('username').value;
  39. const password = document.getElementById('password').value;
  40. // 使用用户名和密码调用登录函数
  41. login(username, password);
  42. });
  43. // 创建处理注销过程的函数
  44. function logOff() {
  45. // 从本地存储中移除身份验证令牌
  46. localStorage.removeItem('token');
  47. // 重定向用户到登录页面
  48. window.location.href = '/loginPage.html';
  49. }
  50. // 附加事件侦听器到注销链接
  51. //document.getElementById('log-off-link').addEventListener('click', logOff);

Spring REST Controller

  1. @RestController
  2. @RequestMapping("/api")
  3. public class WSMController {
  4. private Map<String, UserSession> sessions = new HashMap<>();
  5. @Autowired
  6. private WSMService service;
  7. @PostMapping(value = "/login")
  8. public ResponseEntity<String> login(@RequestBody LoginRequest request) {
  9. User user = authenticate(request);
  10. if (user == null) {
  11. return ResponseEntity.badRequest().body("无效的用户名或密码");
  12. }
  13. String token = UUID.randomUUID().toString();
  14. UserSession session = new UserSession(user, token);
  15. sessions.put(token, session);
  16. return ResponseEntity.ok(token);
  17. }
  18. @PostMapping("/logoff")
  19. public ResponseEntity<String> logoff(@RequestHeader("Authorization") String token) {
  20. sessions.remove(token.substring(7));
  21. return ResponseEntity.ok("用户成功注销");
  22. }
  23. @GetMapping("/user")
  24. public User getUser(@RequestHeader("Authorization") String token) {
  25. UserSession session = sessions.get(token.substring(7));
  26. if (session == null) {
  27. return null;
  28. }
  29. return session.getUser();
  30. }
  31. private User authenticate(LoginRequest request) {
  32. if(!service.getCredentials(request)) {
  33. return null;
  34. }
  35. return new User(request.getUsername(),request.getPassword());
  36. }
  37. }

LoginRequest DTO

  1. package com.worksoftmanager.WorkSoftManagerAuthenticator.model;
  2. public class LoginRequest {
  3. private String username;
  4. private password;
  5. public String getUsername() {
  6. return username;
  7. }
  8. public void setUsername(String username) {
  9. this.username = username;
  10. }
  11. public String getPassword() {
  12. return password;
  13. }
  14. public void setPassword(String password) {
  15. this.password = password;
  16. }
  17. }

这是服务器端的错误消息:

  1. 2023-02-06 10:43:10.674 WARN 20380 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain;charset=UTF-8' not supported]

我已尝试设置头部以发送"application/json"内容并更改RequestMapping以消耗"Application_JSON_Value",但都没有成功。

英文:

I'm trying to send a POST from my javascript file to a server local host which will validate the login.

Here is my front end code:

HTML

  1. &lt;!DOCTYPE html&gt;
  2. &lt;html&gt;
  3. &lt;head&gt;
  4. &lt;meta charset=&quot;UTF-8&quot;&gt;
  5. &lt;title&gt;WorkSoftManager - Login&lt;/title&gt;
  6. &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;styleLogin.css&quot;&gt;
  7. &lt;/head&gt;
  8. &lt;body&gt;
  9. &lt;div class=&quot;container&quot;&gt;
  10. &lt;h1&gt;WorkSoftManager&lt;/h1&gt;
  11. &lt;h2&gt;Login&lt;/h2&gt;
  12. &lt;form id=&quot;login-form&quot;&gt;
  13. &lt;input type=&quot;email&quot; id=&quot;username&quot; placeholder=&quot;Email&quot; required&gt;
  14. &lt;input type=&quot;password&quot; id=&quot;password&quot; placeholder=&quot;Password&quot; required&gt;
  15. &lt;button type=&quot;submit&quot;&gt;Login&lt;/button&gt;
  16. &lt;/form&gt;
  17. &lt;p&gt;Don&#39;t have an account? &lt;a href=&quot;signUp.html&quot;&gt;Sign Up&lt;/a&gt;&lt;/p&gt;
  18. &lt;/div&gt;
  19. &lt;script src=&quot;script.js&quot;&gt;&lt;/script&gt;
  20. &lt;/body&gt;
  21. &lt;/html&gt;

JavaScript

  1. // Create a function to handle the login process
  2. async function login(username, password) {
  3. try {
  4. const response = await fetch(&#39;http://localhost:8080/api/login/&#39;, {
  5. method: &#39;POST&#39;,
  6. mode: &#39;no-cors&#39;,
  7. headers: {
  8. &#39;Content-Type&#39;: &#39;application/json&#39;
  9. },
  10. body: JSON.stringify({
  11. &#39;username&#39; : username,
  12. &#39;password&#39;: password
  13. })
  14. });
  15. // Check if the response was successful
  16. if (!response.ok) {
  17. throw new Error(&#39;Login failed. Please try again.&#39;);
  18. }
  19. // Parse the response JSON data
  20. const data = await response.json();
  21. // Check if the authentication was successful
  22. if (!data.authenticated) {
  23. throw new Error(&#39;Invalid username or password.&#39;);
  24. }
  25. // Store the authentication token in local storage
  26. localStorage.setItem(&#39;token&#39;, data.token);
  27. // Redirect the user to the loginPage.html page
  28. window.location.href = &#39;/loginPage.html&#39;;
  29. } catch (error) {
  30. // Show an error message
  31. alert(error.message);
  32. }
  33. }
  34. // Attach an event listener to the login form submit button
  35. document.getElementById(&#39;login-form&#39;).addEventListener(&#39;submit&#39;, (event) =&gt; {
  36. event.preventDefault();
  37. // Get the values of the username and password inputs
  38. const username = document.getElementById(&#39;username&#39;).value;
  39. const password = document.getElementById(&#39;password&#39;).value;
  40. // Call the login function with the username and password
  41. login(username, password);
  42. });
  43. // Create a function to handle the log off process
  44. function logOff() {
  45. // Remove the authentication token from local storage
  46. localStorage.removeItem(&#39;token&#39;);
  47. // Redirect the user to the login page
  48. window.location.href = &#39;/loginPage.html&#39;;
  49. }
  50. // Attach an event listener to the log off link
  51. //document.getElementById(&#39;log-off-link&#39;).addEventListener(&#39;click&#39;, logOff);

Spring REST Controller

  1. @RestController
  2. @RequestMapping(&quot;/api&quot;)
  3. public class WSMController {
  4. private Map&lt;String, UserSession&gt; sessions = new HashMap&lt;&gt;();
  5. @Autowired
  6. private WSMService service;
  7. @PostMapping(value = &quot;/login&quot;)
  8. public ResponseEntity&lt;String&gt; login(@RequestBody LoginRequest request) {
  9. User user = authenticate(request);
  10. if (user == null) {
  11. return ResponseEntity.badRequest().body(&quot;Invalid username or password&quot;);
  12. }
  13. String token = UUID.randomUUID().toString();
  14. UserSession session = new UserSession(user, token);
  15. sessions.put(token, session);
  16. return ResponseEntity.ok(token);
  17. }
  18. @PostMapping(&quot;/logoff&quot;)
  19. public ResponseEntity&lt;String&gt; logoff(@RequestHeader(&quot;Authorization&quot;) String token) {
  20. sessions.remove(token.substring(7));
  21. return ResponseEntity.ok(&quot;User logged off successfully&quot;);
  22. }
  23. @GetMapping(&quot;/user&quot;)
  24. public User getUser(@RequestHeader(&quot;Authorization&quot;) String token) {
  25. UserSession session = sessions.get(token.substring(7));
  26. if (session == null) {
  27. return null;
  28. }
  29. return session.getUser();
  30. }
  31. private User authenticate(LoginRequest request) {
  32. if(!service.getCredentials(request)) {
  33. return null;
  34. }
  35. return new User(request.getUsername(),request.getPassword());
  36. }

LoginRequest DTO

  1. package com.worksoftmanager.WorkSoftManagerAuthenticator.model;
  2. public class LoginRequest {
  3. private String username;
  4. private String password;
  5. public String getUsername() {
  6. return username;
  7. }
  8. public void setUsername(String username) {
  9. this.username = username;
  10. }
  11. public String getPassword() {
  12. return password;
  13. }
  14. public void setPassword(String password) {
  15. this.password = password;
  16. }
  17. }

Here is the error message from server side:

  1. 2023-02-06 10:43:10.674 WARN 20380 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type &#39;text/plain;charset=UTF-8&#39; not supported]

I've tried set the headers to send an application/json content and change the RequestMapping to consume Application_JSON_Value, but none of it worked.

---------Testing response-----------:

----John's response:

Spring Boot 返回错误:不支持内容类型 ‘text/plain;charset=UTF-8’。

After I make the request, I got this message on console:

Spring Boot 返回错误:不支持内容类型 ‘text/plain;charset=UTF-8’。

Error using await response.json()

enter image description here

----David's response:

Headers:

enter image description here

Body:

enter image description here

答案1

得分: 0

我认为这个 JSON 不好。尝试:

  1. body: JSON.stringify({
  2. 'username': username,
  3. 'password': password
  4. })

另外,mode: 'no-cors' 会强制 content-type 为文本。要么将其移除,要么设置为 mode: 'cors' - 参见 no-cors breaks content-type header

英文:

I think that the JSON isn't good. Try

  1. body: JSON.stringify({
  2. &#39;username&#39; : username,
  3. &#39;password&#39;: password
  4. })

Also the mode: &#39;no-cors&#39; will force the content-type to text. Either take it out or set mode: &#39;cors&#39; - see no-cors breaks content-type header

答案2

得分: 0

@PostMapping 或其他映射可以设置特定的输入/输出 ContentTypes

  1. @PostMapping(path = "/login", consumes = "application/json", produces = "application/json")
  2. public ResponseEntity<String> login(@RequestBody LoginRequest request) {
  3. ...
  4. return ResponseEntity;
  5. }

其他了解 Spring @PostMapping 的参考:

(Baeldung) @RequestMapping Consumes and Produces

(Stackoverflow) What is produce and consume in @Request Mapping

对于 JavaScript 部分,问题出在 mode: 'no-cors'

JavaScript no-cors answer

解决方法之一是更改 Java 代码:
JSON to Java Object

  1. @PostMapping(path = "/login", consumes = "text/plain", produces = "application/json")
  2. public ResponseEntity<String> login(@RequestBody String request) {
  3. ObjectMapper objectMapper = new ObjectMapper();
  4. LoginRequest loginRequest = objectMapper.readValue(json, LoginRequest.class);
  5. ...
  6. return ResponseEntity;
  7. }
英文:

@PostMapping or other mappings can be set to specific input/output ContentTypes

  1. @PostMapping(path = &quot;/login&quot;, consumes = &quot;application/json&quot;, produces = &quot;application/json&quot;)
  2. public ResponseEntity&lt;String&gt; login(@RequestBody LoginRequest request) {
  3. ...
  4. return ResponseEntity;
  5. }

Other references to understand Spring @PostMapping:

(Baeldung) @RequestMapping Consumes and Produces

(Stackoverflow) What is produce and consume in @Request Mapping

For the JavaScript part.
The problem is with mode: &#39;no-cors&#39;

JavaScript no-cors answer

A way to get arround with that is changing the java:
JSON to Java Object

  1. @PostMapping(path = &quot;/login&quot;, consumes = &quot;text/plain&quot;, produces = &quot;application/json&quot;)
  2. public ResponseEntity&lt;String&gt; login(@RequestBody String request) {
  3. ObjectMapper objectMapper = new ObjectMapper();
  4. LoginRequest loginRequest = objectMapper.readValue(json, LoginRequest.class);
  5. ...
  6. return ResponseEntity;
  7. }

huangapple
  • 本文由 发表于 2023年2月6日 21:55:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75362235.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定