admin管理员组

文章数量:1568304

单点登录

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

原理

有一个独立的认证中心,只有认证中心才能接受用户的用户名和密码等信息进行认证,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,当用户提供的用户名和密码通过认证中心认证后,认证中心会创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌即得到了授权,然后创建局部会话。用户在登录之前访问未授权页面会跳到认证中心进行认证,认证成功后返回之前系统的主界面。

https://wwwblogs/zhuchenglin/p/8968530.html

优点

1)提高用户的效率。

用户不再被多次登录困扰,也不需要记住多个 ID 和密码。另外,用户忘记密码并求助于支持人员的情况也会减少。

2)提高开发人员的效率。

SSO 为开发人员提供了一个通用的身份验证框架。实际上,如果 SSO 机制是独立的,那么开发人员就完全不需要为身份验证操心。他们可以假设,只要对应用程序的请求附带一个用户名,身份验证就已经完成了。

3)简化管理。

如果应用程序加入了单点登录协议,管理用户帐号的负担就会减轻。简化的程度取决于应用程序,因为 SSO 只处理身份验证。所以,应用程序可能仍然需要设置用户的属性(比如访问特权)

 

单点登录的系统实现

单点登录代码分为需求端和服务端,需求端为需要登陆的具体系统,服务端为登陆服务器负责用户名密码校验。

单点登录的需求端项目结构

1、新建一个Springboot项目,添加依赖

<dependency>    
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-redis</artifactId>
    <version>1.0.0.RELEASE</version>
</dependency>

2、UserController实现页面跳转

@Controller
public class UserController {
    @RequestMapping(value = "/{pageName}")
    public ModelAndView login(ModelAndView mv,@PathVariable String pageName) {
	mv.setViewName(pageName);
	return mv;
    }
    
    @RequestMapping(value = "/")
    public ModelAndView login(ModelAndView mv) {
    	mv.setViewName("index");
    	return mv;
    }
}

3、添加拦截器

 在这里拦截器如果发现没有登录会跳转到认证中心的登录界面

@Component
public class LoginHandlerInterceptor implements HandlerInterceptor {

    public static final String COOKIE_NAME = "USER_TOKEN";
    @Autowired
    private UserService userService;
	
    // 目标方法执行之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    	String token = CookieUtils.getCookieValue(request, COOKIE_NAME);
    	User user =userService.queryUserByToken(token);
        // 如果获取的request的session中的loginUser参数为空(未登录),就返回登录页,否则放行访问+"&address="+address
        if (user == null) {
            String url = request.getRequestURL().toString();
            // 未登录,给出错误信息,
            request.setAttribute("name","无权限请先登录");
            // 获取request返回页面到登录页
            response.sendRedirect("http://localhost:8081/loginPage?redirect=" + url);
            return false;
        } else {
            // 已登录,放行
            request.setAttribute("user", user);
            return true;
        }
    }

    @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 {
    }
}

拦截器配置WebConfig.java

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware{
    
    @SuppressWarnings("unused")
	private ApplicationContext applicationContext;
    
    @Autowired
    LoginHandlerInterceptor loginHandlerInterceptor;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截的请求,并排除几个不拦截的请求
        registry.addInterceptor(loginHandlerInterceptor).addPathPatterns("/**")
                 .excludePathPatterns("/demo");
    }
    
}

4、添加用户服务 UserService.java

根据token从redis中查询用户信息判断是否登录

@Service 
@Transactional 
public class UserService {     

	@Autowired    
	private RedisUtil redisUtil;     
  
	public User queryUserByToken(String token) throws Exception {
		// 根据token从redis中查询用户信息
		String json = redisUtil.get("REDIS_USER_SESSION:" + token);
		// 判断是否为空  
		if (StringUtils.isEmpty(json)) {
			return null;         
		}         
		// 更新过期时间         
		redisUtil.expire("REDIS_USER_SESSION:" + token, 600);
		// 返回用户信息        
		return JsonUtils.objectFromJsonStr(json, User.class);     
	}
}

5、添加实体类

 TitResult.java

public class TitResult {

	//响应代码
	private Integer code;	

	//响应消息
	private String msg;
	 
	//响应数据
	private Object data;
	
	public TitResult() {
	}

	public TitResult(Integer code, String msg, Object data) {
		this.code = code;
		this.msg = msg;
		this.data = data;
	}
	
	public static TitResult getTitResult(Integer code, String msg, Object data){
		return new TitResult(code, msg, data);
	}
	
	public static TitResult getTitResult(Integer code, String msg){
		return new TitResult(code, msg, null);
	}
	
	public static TitResult success(Object data){
		return new TitResult(200, "", data);
	}
        
        //…………getter setter…………
}

User.java

public class User {

	private String name;
	
	private String password;

	public User() {
		super();
	}
	
	public User(String name, String password) {
		super();
		this.name = name;
		this.password = password;
	}

        //…………getter setter…………
}

6、添加工具类

Cookie工具类 :https://blog.csdn/qq_36154832/article/details/90716860

JsonUtils工具类:https://blog.csdn/qq_36154832/article/details/90719543

RedisUtil工具类: https://blog.csdn/qq_36154832/article/details/90719467

7、html界面

demo.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>demo page</title>
</head>
<body>
<h2>我随时可以访问</h2>
</body>
</html>

index.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>index page</title>
</head>
<body>
<h2>主页面</h2>
</body>
</html>

8、application.properties

#端口号
server.port=8080
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379 

下篇地址

https://blog.csdn/qq_36154832/article/details/90730915

本文标签: 单点简单功能SpringBootthymeleaf