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

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

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

问题

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

这是我的前端代码:

HTML

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>WorkSoftManager - 登录</title>
    <link rel="stylesheet" type="text/css" href="styleLogin.css">
  </head>
  <body>
    <div class="container">
      <h1>WorkSoftManager</h1>
      <h2>登录</h2>
      <form id="login-form">
        <input type="email" id="username" placeholder="电子邮件" required>
        <input type="password" id="password" placeholder="密码" required>
        <button type="submit">登录</button>
      </form>
      <p>没有账户?<a href="signUp.html">注册</a></p>
    </div>
    <script src="script.js"></script>
  </body>
</html>

JavaScript

// 创建处理登录过程的函数
async function login(username, password) {
    try {
        const response = await fetch('http://localhost:8080/api/login/', {
            method: 'POST',
            mode: 'no-cors',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({
              'username': username,
              'password': password
            })
        });

  
      // 检查响应是否成功
      if (!response.ok) {
        throw new Error('登录失败。请重试。');
      }
  
      // 解析响应的JSON数据
      const data = await response.json();
  
      // 检查身份验证是否成功
      if (!data.authenticated) {
        throw an Error('无效的用户名或密码。');
      }
  
      // 将身份验证令牌存储在本地存储中
      localStorage.setItem('token', data.token);
  
      // 重定向用户到loginPage.html页面
      window.location.href = '/loginPage.html';
    } catch (error) {
      // 显示错误消息
      alert(error.message);
    }
  }

  
  // 附加事件侦听器到登录表单的提交按钮
  document.getElementById('login-form').addEventListener('submit', (event) => {
    event.preventDefault();
  
    // 获取用户名和密码输入的值
    const username = document.getElementById('username').value;
    const password = document.getElementById('password').value;
  
    // 使用用户名和密码调用登录函数
    login(username, password);
  });
  

  // 创建处理注销过程的函数
    function logOff() {
        // 从本地存储中移除身份验证令牌
        localStorage.removeItem('token');
    
        // 重定向用户到登录页面
        window.location.href = '/loginPage.html';
    }
  
  // 附加事件侦听器到注销链接
  //document.getElementById('log-off-link').addEventListener('click', logOff);

Spring REST Controller

@RestController
@RequestMapping("/api")
public class WSMController {

    private Map<String, UserSession> sessions = new HashMap<>();

    @Autowired
    private WSMService service;

    @PostMapping(value = "/login")
    public ResponseEntity<String> login(@RequestBody LoginRequest request) {
        User user = authenticate(request);
        if (user == null) {
            return ResponseEntity.badRequest().body("无效的用户名或密码");
        }
        String token = UUID.randomUUID().toString();
        UserSession session = new UserSession(user, token);
        sessions.put(token, session);
        return ResponseEntity.ok(token);
    }

    @PostMapping("/logoff")
    public ResponseEntity<String> logoff(@RequestHeader("Authorization") String token) {
        sessions.remove(token.substring(7));
        return ResponseEntity.ok("用户成功注销");
    }

    @GetMapping("/user")
    public User getUser(@RequestHeader("Authorization") String token) {
        UserSession session = sessions.get(token.substring(7));
        if (session == null) {
            return null;
        }
        return session.getUser();
    }

    private User authenticate(LoginRequest request) {
        if(!service.getCredentials(request)) {
            return null;
        }

        return new User(request.getUsername(),request.getPassword());
    }
}

LoginRequest DTO

package com.worksoftmanager.WorkSoftManagerAuthenticator.model;

public class LoginRequest {

    private String username;
    private password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

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

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

&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;WorkSoftManager - Login&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;styleLogin.css&quot;&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div class=&quot;container&quot;&gt;
      &lt;h1&gt;WorkSoftManager&lt;/h1&gt;
      &lt;h2&gt;Login&lt;/h2&gt;
      &lt;form id=&quot;login-form&quot;&gt;
        &lt;input type=&quot;email&quot; id=&quot;username&quot; placeholder=&quot;Email&quot; required&gt;
        &lt;input type=&quot;password&quot; id=&quot;password&quot; placeholder=&quot;Password&quot; required&gt;
        &lt;button type=&quot;submit&quot;&gt;Login&lt;/button&gt;
      &lt;/form&gt;
      &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;
    &lt;/div&gt;
    &lt;script src=&quot;script.js&quot;&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;

JavaScript

// Create a function to handle the login process
async function login(username, password) {
    try {
        const response = await fetch(&#39;http://localhost:8080/api/login/&#39;, {
            method: &#39;POST&#39;,
            mode: &#39;no-cors&#39;,
            headers: {
              &#39;Content-Type&#39;: &#39;application/json&#39;
            },
            body: JSON.stringify({
              &#39;username&#39; : username,
              &#39;password&#39;: password
            })
        });

  
      // Check if the response was successful
      if (!response.ok) {
        throw new Error(&#39;Login failed. Please try again.&#39;);
      }
  
      // Parse the response JSON data
      const data = await response.json();
  
      // Check if the authentication was successful
      if (!data.authenticated) {
        throw new Error(&#39;Invalid username or password.&#39;);
      }
  
      // Store the authentication token in local storage
      localStorage.setItem(&#39;token&#39;, data.token);
  
      // Redirect the user to the loginPage.html page
      window.location.href = &#39;/loginPage.html&#39;;
    } catch (error) {
      // Show an error message
      alert(error.message);
    }
  }

  
  // Attach an event listener to the login form submit button
  document.getElementById(&#39;login-form&#39;).addEventListener(&#39;submit&#39;, (event) =&gt; {
    event.preventDefault();
  
    // Get the values of the username and password inputs
    const username = document.getElementById(&#39;username&#39;).value;
    const password = document.getElementById(&#39;password&#39;).value;
  
    // Call the login function with the username and password
    login(username, password);
  });
  

  // Create a function to handle the log off process
    function logOff() {
        // Remove the authentication token from local storage
        localStorage.removeItem(&#39;token&#39;);
    
        // Redirect the user to the login page
        window.location.href = &#39;/loginPage.html&#39;;
    }
  
  // Attach an event listener to the log off link
  //document.getElementById(&#39;log-off-link&#39;).addEventListener(&#39;click&#39;, logOff);

Spring REST Controller

@RestController
@RequestMapping(&quot;/api&quot;)
public class WSMController {

    private Map&lt;String, UserSession&gt; sessions = new HashMap&lt;&gt;();

    @Autowired
    private WSMService service;

    @PostMapping(value = &quot;/login&quot;)
    public ResponseEntity&lt;String&gt; login(@RequestBody LoginRequest request) {
        User user = authenticate(request);
        if (user == null) {
            return ResponseEntity.badRequest().body(&quot;Invalid username or password&quot;);
        }
        String token = UUID.randomUUID().toString();
        UserSession session = new UserSession(user, token);
        sessions.put(token, session);
        return ResponseEntity.ok(token);
    }

    @PostMapping(&quot;/logoff&quot;)
    public ResponseEntity&lt;String&gt; logoff(@RequestHeader(&quot;Authorization&quot;) String token) {
        sessions.remove(token.substring(7));
        return ResponseEntity.ok(&quot;User logged off successfully&quot;);
    }

    @GetMapping(&quot;/user&quot;)
    public User getUser(@RequestHeader(&quot;Authorization&quot;) String token) {
        UserSession session = sessions.get(token.substring(7));
        if (session == null) {
            return null;
        }
        return session.getUser();
    }

    private User authenticate(LoginRequest request) {
        if(!service.getCredentials(request)) {
            return null;
        }

        return new User(request.getUsername(),request.getPassword());
    }

LoginRequest DTO

package com.worksoftmanager.WorkSoftManagerAuthenticator.model;

public class LoginRequest {

    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

Here is the error message from server side:

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 不好。尝试:

body: JSON.stringify({
  'username': username,
  'password': password
})

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

英文:

I think that the JSON isn't good. Try

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

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

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

其他了解 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

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

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

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

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

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

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:

确定