前言
vue-element-admin的修改点这个这是前端部分
本文用一个demo介绍如何获取运用spring-boot配置后台的跨域和拦截器,再配合前端返回获取用户的信息的过程。数据库用JPA进行查询,token用JWT生成。
一、跨域和拦截器的配置
新建文件夹config在问价夹下新建MyWebConfigure.java和LoginInterceptor.java
在LoginInterceptor.java中配置拦截器,再在MyWebConfigure.java中使用。拦截器会拦截excludePathPatterns()以外的所有路径。
1. 跨域的配置
主要代码如下:
@SpringBootConfiguration
public class MyWebConfigurer implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
//所有请求都允许跨域,使用这种配置方法就不用在 interceptor 中再配置 header 了
registry.addMapping("/**")
.allowCredentials(true)
.allowedOrigins("http://localhost:9528")
.allowedOrigins("*")//允许跨域访问的路径
.allowedMethods("*")
.allowedHeaders("*")
.maxAge(3600);
}
//使用拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
//所有路径都被拦截
.addPathPatterns("/**")
//添加不拦截的路径
.excludePathPatterns("/register","/login");
}
}
2.拦截器配置
拦截器中配置跨域信息避免拦截器和跨域冲突造成浏览器报跨域错误
preHandle无法调用封装的数据返回类可以在preHandle中用response给前端返回信息
public class LoginInterceptor implements HandlerInterceptor {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
boolean flag;
//在拦截器中设置允许跨域 避免拦截器和跨域的配置冲突导致跨域报错
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers","*");
response.setHeader("Access-Control-Allow-Methods","*");
response.setHeader("Access-Control-Allow-Credentials","true");
response.setHeader("Access-Control-Max-Age","3600");
//放行静态资源
if (handler instanceof ResourceHttpRequestHandler)
return true;
//验证token信息是否正确
//获取请求头中的token 注意getHeader和前端配置的要相同
String token = request.getHeader("x-token");
if(token==null){
//在拦截器中给前端返回信息
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
JSONObject res = new JSONObject();
res.put("code","502");
res.put("message","token为空!");
PrintWriter out = null ;
out = response.getWriter();
out.write(res.toString());
out.flush();
out.close();
return false;
}else {
try {
JwtParser parser = Jwts.parser();
parser.setSigningKey("miyao");
Jws<Claims> ClaimsJws =parser.parseClaimsJws(token);
return true;
}catch (Exception e){
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
JSONObject res = new JSONObject();
res.put("code","505");
res.put("message","登录验证失败!");
PrintWriter out = null ;
out = response.getWriter();
out.write(res.toString());
out.flush();
out.close();
return false;
}
}
}
}
二、Service层中的验证登录和获取用户信息接口
RetResponse 是自己封装的返回类型,MD5Utils是封装的一个简单的密码加密工具类。不要也可以去掉直接获取明文的密码和数据库进行对比。
主要代码如下:
@Service
public class CheckLoginService {
@Autowired
UserDao userDao;
public RetResponse CheckLogin(String username, String pwd) {
String Md5pwd = MD5Utils.md5(pwd);
//判断登录成功后生成token
User u = userDao.findByName(username);
if (u != null) {
if (Md5pwd.equals(u.getPassword())) {
//如果验证成功生成token 在验证token的正确
JwtBuilder builder = Jwts.builder();
HashMap<String, Object> map = new HashMap<>();
map.put("uid", u.getId());//储存用户ID到token中
builder.setSubject(username)//主题token中携带的数据
.setIssuedAt(new Date())//设置token的生成时间
.setId(u.getId() + "")//设置用户id为token的id
.setClaims(map)//map中可以放用户的角色信息 管理员等
.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000))//设置token过期时间
.signWith(SignatureAlgorithm.HS256, "miyao")//设置加密方式和加密密码
.compact();
//返回token builder.compact()
return RetResponse.SuccessToken(builder.compact());
} else {
return RetResponse.ErrRsp("账户或密码错误!");
}
} else {
return RetResponse.ErrRsp("账户或密码错误!");
}
}
/*获取用户信息*/
public User GetUserInfo(String token) {
//解析token中的uid 获取用户信息
Claims claims;
claims = Jwts.parser()
.setSigningKey("miyao")
.parseClaimsJws(token)
.getBody();
int uid = (int) claims.get("uid");
return userDao.findById(uid);
}
}
三.Dao层
UserDao接口文件:
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserDao extends JpaRepository<User,Integer> {
User findById(int id);
User findByName(String Username);
}
四.controller层
代码如下:
/*登录*/
@PostMapping(value = "/login")
public RetResponse login(@RequestBody Map<String, Object> ci) {
String name = String.valueOf(ci.get("username"));
String pwd = String.valueOf(ci.get("password"));
return checkLoginService.CheckLogin(name, pwd);
}
/*
*获取用户信息
*/
@GetMapping(value = "/getUserinfo")
public RetResponse GetUserinfo(@RequestHeader Map headers) {
/*获取请求头中的token也可以用GetUserinfo(HttpServletRequest request)
String token = request.getHeader("token");*/
String token = (String) headers.get("x-token");
return RetResponse.SuccessRsp(checkLoginService.GetUserInfo(token));
}
五.数据库
数据库就两张表 User和roleItem表,user表包含id,name,password,avatar,roleId
roleItem包含id,name,describe
总结
一个简单的登录流程demo