使用前端缓存cookie的方式实现,十分不安全
后端:
org.springframework.boot spring-boot-starter-web
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@Controller
public class LoginController {
@GetMapping("/")
public String index() {
return "index";
}
@PostMapping("/login")
public String login(@RequestParam("username") String username,
@RequestParam("password") String password,
HttpServletResponse response) {
// 进行用户名和密码的验证逻辑
if (isValidUser(username, password)) {
// 验证通过,创建一个Cookie保存用户登录信息
Cookie cookie = new Cookie("user", username);
cookie.setMaxAge(86400); // 设置Cookie有效期为1天
response.addCookie(cookie);
// 重定向到登录成功页面
return "redirect:/success";
} else {
// 验证失败,返回登录页面
return "redirect:/?error=1";
}
}
@GetMapping("/success")
public String success() {
return "success";
}
private boolean isValidUser(String username, String password) {
// 在实际应用中,这里可以进行用户名和密码的验证逻辑,比如查询数据库或调用API等
// 这里只是一个示例,始终返回true来模拟验证通过
return true;
}
}
前端:
Cookie 示例 Cookie 示例
后端保存会话(redis),前端发信息
org.springframework.boot spring-boot-starter-session org.springframework.boot spring-boot-starter-data-redis
# Redis 连接配置 spring.redis.host=localhost spring.redis.port=6379
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@SpringBootApplication
@EnableRedisHttpSession
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
实现session,Spring 会自动使用 Redis 来管理 HttpSession。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@RestController
public class MyController {
@GetMapping("/profile")
public String getProfile(HttpSession session) {
// 从会话中获取用户信息
String username = (String) session.getAttribute("username");
if (username != null) {
return "Username: " + username;
} else {
return "Not logged in";
}
}
}
前端:
// 后端返回的响应中包含 session ID
const sessionID = '1234567890';
// 前端将 session ID 存储在 LocalStorage 中
localStorage.setItem('sessionID', sessionID);
// 发送请求时手动将 session ID 携带在请求头中或请求参数中
fetch('/profile', {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('sessionID')
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
// 成功获取到用户资料信息
console.log(data);
} else {
// 未登录,进行相应处理
console.log('未登录');
}
});
特点:一次登录,到处畅通。
使用sso微服务去认证,通过后保存token,再次验证时出示凭证即可获取登录信息。

com.auth0 java-jwt 3.8.3 io.jsonwebtoken jjwt 0.9.1
@RequestMapping("/login")
public Map login(String userName, String password){
Map map=new HashMap<>();
try{
String token = Jwts.builder().setSubject(userName) //主题,可以放用户的详细信息
.setIssuedAt(new Date()) //token创建时间
.setExpiration(new Date(System.currentTimeMillis() + 60000)) //token过期时间
.setId("userId") //用户ID
//.setClaims(hashMap) //配置角色信息
.signWith(SignatureAlgorithm.HS256, "WuHan") //加密方式和加密密码
.compact();
// System.out.println("token:"+token);
map.put("code","1");
map.put("msg","success");
map.put("token",token);
map.put("user",userName);
}catch (Exception e){
map.put("code","0");
map.put("msg","fail");
e.printStackTrace();
}
return map;
}
token示例如下:
token:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4YyIsImlhdCI6MTU5MTE1NDQwNiwiZXhwIjoxNTkxMTU0NDY2LCJqdGkiOiJ1c2VySWQifQ.c7gCDgIQ_I40dIWRxyG4yd1xaZQyWflnC7kX2Uoc9H8
token构成包含三个部分:
注意事项:
①根据需求设计过期时间(1秒 =1000 毫秒 )
②因为我把时间设计到token里面了所以你可以测试每次产生的token不一样
③设置userId那一栏-我目前是写死了 setId(“userId”) ,你可以根据需求设计不同的值进去
try {
JwtParser parser = Jwts.parser();
parser.setSigningKey("WuHan");//解析 要和上面“暗号”一样
Jws claimsJws = parser.parseClaimsJws(token);
Claims body = claimsJws.getBody();
String username = body.getSubject();
// Object role = body.get("role");
return true;
} catch (ExpiredJwtException e) {
e.printStackTrace();
} catch (UnsupportedJwtException e) {
e.printStackTrace();
} catch (MalformedJwtException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
setSigningKey()与builder中签名方法signWith()对应,parser中的此方法拥有与signWith()方法相同的三种参数形式,用于设置JWT的签名key,用户后面对JWT进行解析。
isSigned() 校验JWT是否进行签名。方法很简单,以分隔符" . ",截取JWT第三段,即签名部分进行判断。
前端:
//需要验证token的页面
补充:
window.sessionStorage(session级别):暂时储存,浏览器关闭之后会清除
window.localStorage (namespace级别):本地储存,浏览器关闭之后依旧不会清除,只能人为删除
/**
* 登录拦截
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getParameter("token");
try {
JwtParser parser = Jwts.parser();
parser.setSigningKey("WuHan");
Jws claimsJws = parser.parseClaimsJws(token);
Claims body = claimsJws.getBody();
String username = body.getSubject();
Object role = body.get("role");
return true;
} catch (ExpiredJwtException e) {
e.printStackTrace();
} catch (UnsupportedJwtException e) {
e.printStackTrace();
} catch (MalformedJwtException e) {
e.printStackTrace();
} catch (SignatureException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Resource
private LoginInterceptor loginInterceptor;
/**
* 添加拦截器
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//.execudePathPatterns()//可以添加不拦截的地址
registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
}
}