SSO单点登录核心原理

登录接口

	@RequestMapping("/doLogin")
	@ResponseBody
	public SysResult login(User user,HttpServletResponse response) {
		//1.校验数据是否正确.获取密钥
		String ticket = userService.findUserByUP(user);
		if(StringUtils.isEmpty(ticket)) {

			return SysResult.fail();
		}
		//2.如果程序执行到这里.表示密钥有值.写入cookie
		Cookie cookie = new Cookie("JT_TICKET", ticket);
		cookie.setMaxAge(7 * 24 * 3600);
		cookie.setPath("/");
		//设定cookie的共享! 这样当访问order.jt.com或者cart.jt.com的时候都会带上这个Cookie
		cookie.setDomain("jt.com");

		//将cookie写入客户端
		response.addCookie(cookie);
		return SysResult.success();
	}

其中userService.findUserByUP(user);方法是:

	@Override
	public String findUserByUP(User user) {
		String ticket = null;
		//为了与数据库数据一致,需要将密码加密
		String md5Pass = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
		user.setPassword(md5Pass);
		QueryWrapper<User> queryWrapper = new QueryWrapper<User>(user);
		//根据用户名和密码校验数据
		User userDB = userMapper.selectOne(queryWrapper);
		if(userDB !=null) {
			//将数据库数据转化为json保存到redis中
			String uuid = UUID.randomUUID().toString();
			ticket = DigestUtils.md5DigestAsHex(uuid.getBytes());
			//进行脱敏处理   100xxx0311  
			userDB.setPassword("123456你信吗??");
			String userJSON = 
					ObjectMapperUtil.toJSON(userDB);
			jedisCluster.setex(ticket,7*24*3600, userJSON);
		}
		return ticket;
	}

拦截器

当访问xxx.jt.com的时候会带上登录返回的Cookie 拦截器中配置了校验Cookie的方法,具体实现如下:

@Component //交给spring容器管理
public class UserInterceptor implements HandlerInterceptor{
	private static final String TICKET = "JT_TICKET";
	
	@Autowired
	private JedisCluster jedisCluster;
	/**
	 * 实现用户权限认证
	 * 	1.用户不登陆,不允许访问涉密操作.重定向到
	 * 	用户登录页面.
	 *  2.如果用户登录,则请求予以放行.
	 *  
	 * 方法说明:
	 * 	1.boolean  
	 * 		true: 放行
	 * 		false: 拦截 配合重定向使用
	 * 实现步骤:
	 * 	1.获取用户的Cookie信息. 获取密钥
	 * 	2.从redis中获取数据.   
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		Cookie[] cookies = request.getCookies();
		String ticket = null;
		//判断cookie是有效的.
		if(cookies.length > 0 ) {
			for (Cookie cookie : cookies) {
				if(TICKET.equals(cookie.getName())) {
					ticket = cookie.getValue();
					break;
				}
			}
		}
		
		if(!StringUtils.isEmpty(ticket)) {
			//校验redis中是否有数据
			String userJSON = jedisCluster.get(ticket);
			if(!StringUtils.isEmpty(userJSON)) {
				//实现用户信息的动态获取
				User user = ObjectMapperUtil.toObject(userJSON,User.class);
				request.setAttribute("JT_USER", user);
				UserThreadLocalUtil.set(user);
				return true;
			}
		}
		
		//如果用户没有登录需要重定向到登录页面
		response.sendRedirect("/user/login.html");
		return false; 
	}
	
	
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		
		//防止内存溢出
		UserThreadLocalUtil.remove();
	}
	
}

其中的UserThreadLocalUtil具体为:

public class UserThreadLocalUtil {
	
	private static 
	ThreadLocal<User> userThread = 
					new ThreadLocal<>();
	
	public static void set(User user) {
		
		userThread.set(user);
	}
	
	public static User get() {
		
		return userThread.get();
	}
	
	public static void remove() {
		
		//防止内存泄漏
		userThread.remove();
	}
}

拦截器配置拦截路径

@Configuration
public class MvcConfigurer implements WebMvcConfigurer{
	
	@Autowired
	private UserInterceptor userInterceptor;
	
	/**
	 * 拦截器路径:
	 * 	/cart/*  拦截url请求中/cart/xxxx 下的一级路径
	 *  /cart/** 拦截cart下的所有路径
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		
		registry.addInterceptor(userInterceptor).addPathPatterns("/cart/**","/order/**");
	}
	
}

退出登录

	/**
	 * 实现用户登出操作.
	 * 	0.获取cookie数据
	 * 	1.删除redis  key~~~ticket
	 * 	2.删除cookie
	 * @return
	 */
	@RequestMapping("/logout")
	public String logout(HttpServletRequest request,HttpServletResponse response) {
		Cookie[] cookies = request.getCookies();
		String ticket = null;
		//判断cookie是有效的.
		if(cookies.length > 0 ) {
			for (Cookie cookie : cookies) {
				if(TICKET.equals(cookie.getName())) {
					ticket = cookie.getValue();
					break;
				}
			}
		}
		
		if(!StringUtils.isEmpty(ticket)) {
			//如果数据不为null,则删除数据
			jedisCluster.del(ticket);
			Cookie cookie = new Cookie(TICKET, "");
			cookie.setMaxAge(0); //立即删除
			cookie.setPath("/");
			cookie.setDomain("jt.com");
			response.addCookie(cookie);
		}
		
		//重定向到系统首页
		return "redirect:/"; 
	}

总结

用户登录后,将返回的凭证塞入Cookie返回给浏览器,并且存一份到Redis(凭证作为key,对应的用户信息为value,并设置对应的过期时间),当用户访问其他同后缀的域名时 比如order.jt.com或者cart.jt.com时,浏览器会自动带上之前的Cookie,拦截器中校验Cookie中存的凭证在Redis中查询是否有该用户,有的话放行,没有重定向到登录页面.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sunny_yiyi

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

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

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

打赏作者

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

抵扣说明:

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

余额充值