kob后端1

文章介绍了SpringBoot应用中的四层架构:POJO、Mapper、Service和Controller,并展示了Mapper层使用MyBatis-Plus进行数据库操作的例子。接着讨论了用户认证的安全性,包括使用BCryptPasswordEncoder进行密码加密和JWT实现跨域验证。文章还给出了登录、获取用户信息及注册的后端API实现,并提到了Ajax跨域问题的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

kob后端

1.四个层;

SpringBoot中的常用模块
pojo层:将数据库中的表对应成Java中的Class
mapper层(也叫Dao层):将pojo层的class中的操作,映射成sql语句
service层:写具体的业务逻辑,组合使用mapper中的操作
controller层:负责请求转发,接受页面过来的参数,传给Service处理,接到返回值,再传给页面

mapper层

mybatis-plus帮我们实现了一些内容,我们不用自己手写sql语句:需要让UserMapper接口继承BaseMapper
queryWrapper数据库动态查询条件;queryWrapper

QueryWrapper实例

    /**
     * 案例三:年龄范围查询(20-30之间的)
     * @return
     */
    @RequestMapping("/list3")
    public Map<String,Object> getList3(){
        Map<String,Object> result = new HashMap<>();

        //构建一个查询的wrapper
        QueryWrapper<User> wrapper = new QueryWrapper<User>();
        //年龄20-30之间的
        wrapper.between("age",20,30);
        //未删除
        wrapper.eq("del_flag",0);
        //创建时间降序
        wrapper.orderByDesc("create_time");

        List<User> list = userMapper.selectList(wrapper);
        result.put("data",list);
        return result;
    }

不会用默认的Username去查询,而是会根据用户名去database中查找用户名和密码,然后再判断用户名和密码是否匹配;
报错Encoding…是因为密码没有加密,如果想要浏览器密码未加密,需要在密码前加上{noop},表示密码是明文未加密:
在这里插入图片描述
实现密码加密:
方式1:session验证
实现config.SecurityConfig类,用来实现用户密码的加密存储

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

SecurityConfig对象一定会调用passwordEncoder()方法,返回使用的那种加密方法:
几个核心API:
在这里插入图片描述
encode将明文转换成密文;
matches:判断明文和密文是否匹配;
方式2:JWT(目前使用较多)验证,对应前后端分离(因为前后端分离存在跨域问题)
在这里插入图片描述
获取到一个url之后,分为两种页面,一种是类似login页面,只要输入url就可以访问,另一种比如根页面,必须经过授权之后才能访问,否则当访问该页面的时候可能会跳转到其他页面比如Login页面:
第一种session验证方式,用户输入用户名密码提交之后,会先根据用户名到用户名进行查找,找到对应的username和password之后,才将其和用户输入的username_input,password_input进行比对,如果比对成功,则通过了验证,此时会给用户发送一个sessionID,用户收到sessionID之后会将sessionID 存到自己的本地(Cookie),未来每次在访问网站的时候,都会自动的将浏览器(cookie)存储的sessionID发送给服务器;前边服务器在将sessionID发送给用户的时候,自己也会存储一份;sessionID对用户来说相对于一个令牌,用户后续在访问页面的时候,会将sessionID令牌带上,服务器在接收到用户想要访问授权页面的请求的时候,会将sessionID从用户发送的请求中提取出来,判断sessionID是否有效,服务器不仅会存储sessionID,实际上是存储了一个sessionID-user的映射,若判断访问服务器的这个链接是有效的话,那么就从服务端将该sessionID对应的用户信息提取出来,提取到上下文中(每一个url都会对应一个controller,通过controller中的某个接口将这个用户提取出来),之后就可以正常访问controller逻辑了;
在这里插入图片描述

jwt验证的优势:
1.实现了跨域;
2.不需要在服务端上存储;(不需要将令牌存储到多个服务器上,有一个Jwt令牌就可以访问多个服务器)
jwt验证原理:
在这里插入图片描述
同理,用户登陆验证通过之后,用户会得一个jwt_token,而服务器给用户发了一个jwt_token之后,自己是不需要存储任何信息的;
那么,如何判断这个用户是哪个用户呢???
将用户的一些信息加入到jwt_token中,如图所示
在这里插入图片描述
用户的user_id+服务端生成的秘钥,通过某种方式进行加密,得到加密后的字符串,再将user_id和加密后的字符串进行拼接,得到了jwt_token,
服务端如何验证呢?
同样获取到user_id,同理给user_id先拼接上秘钥,然后根据固定的加密方法(同上述步骤一样),判断用户传过来的jwt_token和根据用户传过来的user_id现生成的jwt_token是不是一样的;
防止他人窃取jwt_token
在这里插入图片描述
一般而言,jwt_token是分为access_token和refresh_token传过来的,access_token时间较短,比如5min,而refresh_token时间较长,
同时,用户的请求有Get(明文,不安全)方式的,也有Post(密文,安全)的,用户在请求的时候会优先使用短时间的令牌,如果短时间的令牌过期了,会重新使用post请求根据refresh_token令牌重新得到一个新的access_token令牌,

Controller

GetMapping注解
如GetMapping(“/user/all/”)

给主键id添加自增注解(@TableId(type= IdType.AUTO)

后端API

1.实现/user/account/token/:验证用户名密码,验证成功后返回jwt token(令牌)
2.实现/user/account/info/:根据令牌返回用户信息
3.+实现/user/account/register/:注册账号

1.在service中写API的接口;
2.在service的impl下写对应API的实现;
3.字controller中写service的调用;

在这里插入图片描述
如图创建如下用户目录,在service目录下创建/user/account/,下写API的接口,在impl下创建相同目录/user/account/下写对应API的实现,

@Service
public class LoginServiceImpl implements LoginService {
    @Override
    public Map<String, String> login(String username, String password) {
        return null;
    }
}

在实现类前要加上Service注解;

一些常用注解的解释
Bean层:
@Autowired:自动导入依赖的bean;

Service层:
@Service:一般用于修饰service层的组件,用于service实现类中;

Controller层
@Controller:用于定义控制器类,在spring项目中由控制器负责将用户发来的URL请求转发到对应的服务接口(service层),一般这个注解在类中,通常方法需要配合注解@RequestMapping。用于定义控制器类

@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。

@GetMapping(链接地址):用于将HTTPGET请求映射到特定处理程序方法的注释。具体来说,@GetMapping是一个作为快捷方式的组合注释@RequestMapping(method = RequestMethod.GET)。

@PostMapping(链接地址),是@RequestMapping(method = RequestMethod.POST)的缩写用于将HTTP POST请求映射到特定处理程序方法的注释。

@RestController:用于标注控制层组件(如struts中的action),@ResponseBody和@Controller的合集。

在实现这三个后端API之前,需要先修改Spring Security(Spring Security 是 Spring 家族中的一个安全管理框架)

1.实现service.impl.UserDetailsServiceImpl类,继承自UserDetailsService接口,用来接入数据库信息

package com.kob.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;//使用任何bean之前,需要先注入

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    	//设置好动态查询条件,通过userMapper在数据库中根据用户名进行查找,如果查找结果不为空,返回用户详细信息对象;
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            throw new RuntimeException("User Does not Exist!");
        }
        return new UserDetailsImpl(user);
    }
}
//用户详细信息UserDetails接口的实现类
package com.kob.backend.service.impl.utils;

import com.kob.backend.pojo.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
@Data
@NoArgsConstructor
@AllArgsConstructor//三个注解表示自动为该类添加get,set,有参构造,无参构造等基本方法
public class UserDetailsImpl implements UserDetails {

    private User user;//这个后添加的,其余全部是实现的接口函数

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return user.getPassword();//这里改成获取密码,原本是null
    }

    @Override
    public String getUsername() {
        return user.getUsername();//这里改成获取用户名,原本是null
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;//改成true,账户为过期?
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;//改成true,账户未锁定?
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;//改成true,凭证未过期?
    }

    @Override
    public boolean isEnabled() {
        return true;//改成true,是否启用?
    }
}

2.实现config.SecurityConfig类,用来实现用户密码的加密存储

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

3.实现utils.JwtUtil类,为jwt工具类,用来创建、解析jwt token

package com.kob.backend.service.impl.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

@Component
public class JwtUtil {
    public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14;  // 有效期14天单位时Ms
    public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds1fsfeseasfesfe21232131afasdfac";//设置再服务端的字符串

    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public static String createJWT(String subject) {
        JwtBuilder builder = getJwtBuilder(subject, null, getUUID());
        return builder.compact();
    }

    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if (ttlMillis == null) {
            ttlMillis = JwtUtil.JWT_TTL;
        }

        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        return Jwts.builder()
                .setId(uuid)
                .setSubject(subject)
                .setIssuer("sg")
                .setIssuedAt(now)
                .signWith(signatureAlgorithm, secretKey)
                .setExpiration(expDate);
    }

    public static SecretKey generalKey() {
        byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");
    }

    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(jwt)
                .getBody();
    }
}

4.实现config.filter.JwtAuthenticationTokenFilter类,用来验证jwt token,如果验证成功,则将User信息注入上下文中

package com.kob.backend.config.filter;

import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import com.kob.backend.service.impl.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private UserMapper userMapper;

    @Override
    protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");

        if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) {
            filterChain.doFilter(request, response);
            return;
        }

        token = token.substring(7);

        String userid;
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userid = claims.getSubject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        User user = userMapper.selectById(Integer.parseInt(userid));

        if (user == null) {
            throw new RuntimeException("用户名未登录");
        }

        UserDetailsImpl loginUser = new UserDetailsImpl(user);
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, null);

        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        filterChain.doFilter(request, response);
    }
}

5.配置config.SecurityConfig类,放行登录、注册等接口

package com.kob.backend.config;

import com.kob.backend.config.filter.JwtAuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/user/account/token/", "/user/account/register/").permitAll()//这里放行
                .antMatchers(HttpMethod.OPTIONS).permitAll()
                .anyRequest().authenticated();

        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }
}
后端API实现1.实现/user/account/token/:验证用户名密码,验证成功后返回jwt token(令牌)

创建LoginService接口,并写出实现类

package com.kob.backend.service.impl.user.account;

import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.JwtUtil;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import com.kob.backend.service.user.account.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class LoginServiceImpl implements LoginService {
    @Autowired//验证用户登陆是否成功;
    private AuthenticationManager authenticationManager;//authenticationManager(身份验证管理器);

    @Override
    public Map<String, String> getToken(String username, String password) {
        //将username和passwd封装成这样的对象之后,就不会存明文了;
        UsernamePasswordAuthenticationToken authenticationToken=new
                UsernamePasswordAuthenticationToken(username,password);//UsernamePasswordAuthenticationToken (用户名密码认证令牌)

        //进行验证;登陆失败会自动处理
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        //登陆成功的话将用户名和密码取出;
        UserDetailsImpl loginUser=(UserDetailsImpl)authenticate.getPrincipal();
        User user=loginUser.getUser();

        //通过用户的userid生成jwt令牌
        String jwt= JwtUtil.createJWT(user.getId().toString());

        Map<String,String> map=new HashMap<>();
        map.put("err_message","success");//不需要处理失败的情况,因为登陆失败的话,Authentication会自动抛出异常,不会执行到这里;
        map.put("token",jwt);

        return map;
    }
}

写出对应的调用controller

package com.kob.backend.controller.user.account;

import com.kob.backend.service.user.account.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class LoginController {

    @Autowired//将定义的接口注入进来
    private  LoginService loginService;

    @PostMapping("/user/account/token/")//登陆通常使用post请求,因为get请求会将用户名和密码暴露在url中,
    //// 括号内为链接地址,可以随意定义,注意该链接需要放行:在SecurityConfig中的configure方法中将该链接添加上;
    public Map<String,String> getToken(@RequestParam Map<String,String> map){//从post请求中将参数拿出来,需加上注解,将post请求中的参数放到一个map中
        //这里的RequestParam注解后需要的参数是从前端发送的post请求中提取出来的;
        String username=map.get("username");
        String password=map.get("password");
        return loginService.getToken(username,password);
    }

}

当前端发送url地址/user/account/token/的Posting请求时,执行对应该链接的方法getToken,从前端发送过来的请求中获取到username,和password,返回该username,password(如果验证通过)的jwt令牌

后端API实现2.实现/user/account/info/根据令牌获取用户信息

InfoServiceImpl:

package com.kob.backend.service.impl.user.account;

import com.kob.backend.pojo.User;
import com.kob.backend.service.impl.utils.UserDetailsImpl;
import com.kob.backend.service.user.account.InfoService;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
public class InfoServiceImpl implements InfoService {
    @Override
    public Map<String, String> getinfo() {
    	//获取到当前的用户,
        UsernamePasswordAuthenticationToken authenticationToken=
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
               
        //将当前的登陆用户取出;
        UserDetailsImpl loginUser=(UserDetailsImpl)authenticationToken.getPrincipal();
        User user=loginUser.getUser();

        Map<String,String> map=new HashMap<>();
        map.put("err_message","success");
        map.put("id",user.getId().toString());
        map.put("username",user.getUsername());
        map.put("password",user.getPassword());
        map.put("photo",user.getPhoto());
        return map;//返回获取到的用户信息;e
    }
}

InfoServiceController类

package com.kob.backend.controller.user.account;

import com.kob.backend.service.user.account.InfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class InfoServiceController {
    @Autowired
    private InfoService infoService;

    @GetMapping("/user/account/info/")
    public Map<String,String> getInfo(){
        return infoService.getinfo();
    }
}
3.实现/user/account/register/:注册账号

实现RegisterServiceImpl类:

package com.kob.backend.service.impl.user.account;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kob.backend.mapper.UserMapper;
import com.kob.backend.pojo.User;
import com.kob.backend.service.user.account.RegisterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class RegisterServiceImpl implements RegisterService {

    @Autowired
    UserMapper userMapper;

    @Autowired
    PasswordEncoder passwordEncoder;//给密码加密的工具类

    @Override
    public Map<String, String> register(String username, String password, String confirmedpasswd) {
        Map<String, String> map = new HashMap<>();
        if (username == null) {
            map.put("err_message", "用户名不能为空");
            return map;
        }
        if (password == null || confirmedpasswd == null) {
            map.put("err_message", "密码不能为空");
            return map;
        }

        username = username.trim();
        if (username.length() == 0) {
            map.put("err_message", "用户名不能为空");
            return map;
        }
        if (password.length() == 0 || confirmedpasswd.length() == 0) {
            map.put("error_message", "密码不能为空");
        }

        if (username.length() > 100) {
            map.put("error_message", "用户名长度不能大于100");
            return map;
        }
        if (password.length() > 100 || confirmedpasswd.length() > 100) {
            map.put("error_message", "密码长度不能大于100");
            return map;
        }

        if (!password.equals(confirmedpasswd)) {
            map.put("error_message", "两次输入的密码不一致");
            return map;
        }

        QueryWrapper<User> queryWrapper=new QueryWrapper<User>();
        queryWrapper.eq("username",username);
        List<User> userList=userMapper.selectList(queryWrapper);
        if(userList!=null){
            map.put("error_message", "用户名已存在");
            return map;
        }

        String encodedPassword=passwordEncoder.encode(password);
        String photo="https://cdn.acwing.com/media/user/profile/photo/180265_lg_5dc3115a2f.png";//设置一个默认头像;
        User user=new User(null,username,encodedPassword,photo);//id设置为null即可,自增;
        userMapper.insert(user);
        map.put("error_message", "success");
        return map;
    }
}

实现controller层:

package com.kob.backend.controller.user.account;

import com.kob.backend.service.user.account.RegisterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;

@RestController
public class RegisterServiceController {
    @Autowired
    private RegisterService registerService;

    @PostMapping("/user/account/register/")
    public Map<String,String> register(@RequestParam Map<String,String> map){
        String username=map.get("username");
        String password=map.get("password");
        String confirmedPasswd=map.get("confirmedPassword");
        return registerService.register(username,password,confirmedPasswd);
    }
}

至此,就实现了登陆,获取用户信息,注册三种功能;

验证的时候可以在打开一个页面,在setup()中使用ajax向指定的url发送数据,之后相应的数据会显示在控制台;

  setup() {
    $.ajax({
      url: 'http://localhost:3000/user/account/token/',
      type: "post",
      data: {
        username: "zhr",
        password: "123456",
      },
      success(resp) {
        console.log(resp);
      },
      error(resp) {
        console.log(resp);
      }
    });

    $.ajax({
      url: "http://127.0.0.1:3000/user/account/register/",
      type: "post",
      data: {
        username: "zhrr",
        password: "114514",
        confirmedPassword: "114514",
      },
      success(resp) {
        console.log(resp);
      },
      error(resp) {
        console.log(resp);
      }
    })
  }

ajax跨域问题解决,在JwtAuthenticationTokenFilter类中添加

 response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有

ajax跨域问题解决

### 回答1kob kt f360 是一款功能强大的家用电风扇,下面是对其说明书的简要介绍: 该电风扇具有三档风速调节功能,可以根据个人需求选择合适的风速,提供舒适的风感体验。同时,还配备有90度自动摇头功能,可以帮助实现更广泛的风向散布,使整个房间都能受到凉爽的风。 kob kt f360 具有创新的静音设计,采用先进的静音技术,减少了噪音干扰,更适合安静的环境使用,不会打扰到您的休息或工作。 该电风扇还内置倒计时功能,可以按照您的需求设置运行时间,设定后自动关闭,方便省电节能。此外,该电风扇还带有室温显示功能,可以让您了解当前环境温度,方便调整风速等。 kob kt f360 采用便捷的遥控器操作,让您可以轻松控制风速、风向等功能,无需离开座位就能自由调节。 此外,kob kt f360 的外观简约大方,采用优质材料制造,耐用性强,易于清洁维护。同时,其紧凑的设计,占据空间小,方便携带和存储。 总之,kob kt f360 是一款功能齐全、操作便捷、静音效果好的电风扇。无论是在家中、办公室还是其他场所使用,都能为您提供舒适、凉爽的环境。同时,其节能环保的设计,也符合现代人的节能理念。 ### 回答2: KOB KT F360是一款先进的电子产品,它具有多种功能和特点。首先,说明书对产品的外观和构造进行了详细描述。你可以从说明书中了解到KOB KT F360采用了高品质的材料和精致的工艺,使其外观时尚而耐用。同时,它的紧凑设计使得携带和使用变得更加方便。 说明书还介绍了KOB KT F360的主要功能和操作方法。它具有多种模式,如音乐播放、视频观看、游戏等,可以满足用户的多样化需求。此外,说明书还详细介绍了产品的操作界面和各个按钮的功能,帮助用户快速上手。 说明书还详细列出了KOB KT F360的技术规格和性能参数。例如,它支持高清屏幕显示,拥有超长续航时间,配置强大的处理器等。这些技术特点的介绍有助于用户了解产品的性能和优势,同时也可以选择最适合自己的使用方法。 最后,说明书还对KOB KT F360的使用注意事项进行了说明。它包括如何避免产品的损坏和电池寿命延长的建议,以及如何正确储存和清洁产品等。 总之,KOB KT F360说明书提供了全面而详细的介绍,帮助用户了解产品的各个方面,并在使用中提供必要的指导和建议。无论是初次使用还是需要更多技术支持的用户,都可以通过说明书获得满意的答案和帮助。 ### 回答3: kob kt f360是一款多功能电子产品,下面为您提供其说明书。 kob kt f360是一款具有多种功能的设备,可以用于各种场景。它具有时尚的外观设计和高品质的制造工艺,给用户带来了极佳的使用体验。 首先,kob kt f360配备了高清显示屏,显示效果清晰细腻。用户可以通过触摸屏幕进行各种操作,非常方便。同时,其内置了强大的处理器,运行速度快,反应灵敏。 其次,kob kt f360还具备丰富的功能。它支持多种文件格式的阅读,包括文档、图片、音频和视频等。用户可以轻松地在这款设备上阅读电子书、浏览照片、收听音乐和观看视频。 此外,kob kt f360还内置了无线网络功能,用户可以轻松地连接到互联网。无论是查找资讯、浏览社交媒体还是收发电子邮件,都非常方便。 值得一提的是,kob kt f360还具备优秀的电池续航能力。它配备了高容量的电池,可以满足用户长时间使用的需求。 最后,kob kt f360还支持外部存储扩展。用户可以通过插入存储卡,扩展设备的存储空间,更方便地存储和分享文件。 总而言之,kob kt f360是一款功能强大、外观时尚的多功能电子产品。它能够满足用户的各种需求,无论是娱乐、办公还是学习,都能轻松应对。拥有这款设备,用户可以更加便捷地享受数字化生活。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黒猫.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值