Redis存储会话
redisOperator.set("userToken:" + users.getId(), token);
CookieUtils.setCookie(request,response,"user",JsonUtils.objectToJson(usersVo),true);
users.setToken(token);
redisOperator.del("userToken:" + userId);
SpringSession实现会话管理
<!-- spring-session依赖 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
spring:
session:
store-type: redis
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
@MapperScan(basePackages = "com.njzy.mapper")扫码mybatis mapper
@EnableScheduling
@EnableRedisHttpSession
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
拦截器配置
- 拦截器的类需要实现HandlerInterceptor
import com.njzy.result.Result;
import com.njzy.utils.JsonUtils;
import com.njzy.utils.RedisOperator;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
public class UserInterceptor implements HandlerInterceptor {
@Autowired
RedisOperator redisOperator;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String token = request.getHeader("token");
String userId = request.getHeader("userId");
if (StringUtils.isBlank(token) || StringUtils.isBlank(userId)) {
returnErrorResponse(response, Result.error("验证失败"));
return false;
}
String value = redisOperator.get("userToken:" + userId);
if (!StringUtils.isBlank(value)) {
if (token.equals(value)) {
returnErrorResponse(response, Result.error("验证成功"));
} else {
returnErrorResponse(response, Result.error("token不匹配,其他客户端登录"));
return false;
}
}
returnErrorResponse(response, Result.error("验证失败"));
return true;
}
private void returnErrorResponse(HttpServletResponse response, Result result) {
OutputStream out = null;
try {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/json");
out = response.getOutputStream();
out.write(JsonUtils.objectToJson(result).getBytes("utf-8"));
out.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@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 {
}
}
import com.njzy.interceptor.UserInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
.addResourceLocations("file:/Users/yuanfang/Downloads/images/");
}
@Bean
public UserInterceptor userInterceptor() {
return new UserInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/doc.html/**", "/swagger-resources", "/v3/api-docs",
"/swagger-ui.html/**", "/webjars/**", "/error",
"/user/checkUsername", "/user/register", "/user/login");
WebMvcConfigurer.super.addInterceptors(registry);
}
}
CAS 系统实现单点登录
- 场景:多套独立的系统使用一套用户体系,在一个系统上登录后,其他系统无需登录,一个系统注销,其他系统需要重新登录
- 由多系统和cas系统组成
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/d5958c1f3ee03314331f5baa8427b0ca.png)
- 单点登录controller代码
import com.njzy.pojo.vo.UsersVo;
import com.njzy.pojo.bo.UsersBo;
import com.njzy.result.Result;
import com.njzy.service.UsersService;
import com.njzy.utils.CookieUtils;
import com.njzy.utils.JsonUtils;
import com.njzy.utils.MD5Util;
import com.njzy.utils.RedisOperator;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
@Controller
public class SSOController {
@Autowired
UsersService usersService;
@Autowired
RedisOperator redisOperator;
private final String COOK_NAME = "cookie_user_ticket";
private final String USER_TOKEN = "userToken";
private final String USER_TICKET = "userTicket";
@GetMapping("/login")
public String sso(String returnUrl, Model model, HttpServletRequest request, HttpServletResponse response) {
model.addAttribute("returnUrl", returnUrl);
String ticket = CookieUtils.getCookieValue(request, COOK_NAME);
if (verifyTicket(ticket)) {
String tempTicket = UUID.randomUUID().toString().trim();
redisOperator.set("useTempTicket:" + tempTicket, MD5Util.md5(tempTicket), 600);
return "redirect:" + returnUrl + "?tempTicket=" + tempTicket;
}
return "login";
}
private boolean verifyTicket(String ticket) {
if (StringUtils.isBlank(ticket)) {
return false;
}
String userId = redisOperator.get(USER_TICKET + ":" + ticket);
if (StringUtils.isBlank(userId)) {
return false;
}
String s = redisOperator.get(USER_TOKEN + ":" + userId);
if (StringUtils.isBlank(s)) {
return false;
}
return true;
}
@PostMapping("/doLogin")
public String doLogin(String username, String password, String returnUrl, Model model, HttpServletRequest request, HttpServletResponse response) {
model.addAttribute("returnUrl", returnUrl);
if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
model.addAttribute("errmsg", "用户名密码不能为空");
return "login";
} else {
UsersBo usersBo = new UsersBo();
usersBo.setUsername(username);
usersBo.setPassword(password);
UsersVo result = usersService.doLogin(usersBo, request, response);
if (result != null) {
String token = UUID.randomUUID().toString().trim();
UsersVo usersVo = new UsersVo();
BeanUtils.copyProperties(result, usersVo);
usersVo.setToken(token);
redisOperator.set(USER_TOKEN + ":" + result.getId(), JsonUtils.objectToJson(usersVo));
} else {
model.addAttribute("errmsg", "用户名密码不正确");
return "login";
}
String ticket = UUID.randomUUID().toString().trim();
CookieUtils.setCookie(request, response, COOK_NAME, ticket);
redisOperator.set(USER_TICKET + ":" + ticket, result.getId());
String tempTicket = UUID.randomUUID().toString().trim();
redisOperator.set("useTempTicket:" + tempTicket, MD5Util.md5(tempTicket), 600);
return "redirect:" + returnUrl + "?tempTicket=" + tempTicket;
}
}
@PostMapping("/verifyTmpTicket")
@ResponseBody
public Result verifyTmpTicket(String tmpTicket, HttpServletRequest request, HttpServletResponse response) {
String tmpTicketValue = redisOperator.get("useTempTicket:" + tmpTicket);
if (StringUtils.isBlank(tmpTicketValue)) {
return Result.error(("用户票据错误"));
}
if (!tmpTicketValue.equals(MD5Util.md5(tmpTicket))) {
return Result.error(("用户票据错误"));
} else {
redisOperator.del("useTempTicket:" + tmpTicket);
}
return Result.success();
}
@PostMapping("/logout")
@ResponseBody
public Result logout(String userId, HttpServletRequest request, HttpServletResponse response) {
String ticket = CookieUtils.getCookieValue(request, COOK_NAME);
CookieUtils.deleteCookie(request, response, COOK_NAME);
redisOperator.del(USER_TICKET + ":" + ticket);
redisOperator.del(USER_TOKEN + ":" + userId);
return Result.success();
}
}