Redis单点登陆系统(SSO)

在分布式系统中,通过会有多个服务,我们登录了一个服务以后,再访问其它服务时,不想再登录,就需要有一套单独的认证系统,我们通常会称之为单点登录系统,在这套系统中提供一个认证服务器,服务完成用户身份认证,在一些中小型分布式系统中中,我们通常会借助redis存储用户的认证信息,例如:

shiro 单点登陆 配合redis 单点登录使用redis_System

 关键代码实现

package com.jt;

import redis.clients.jedis.Jedis;

import java.util.UUID;

/**
 * 基于redis的单点登录设计及实现
 * 1)用户登录成功以后将登录状态等信息存储到redis
 * 2)用户携带token去访问资源,资源服务器要基于token从redis查询用户信息
 */
public class SSODemo01 {
    /**
     * 执行登录认证,将来这样的业务要写到认证服务器
     * @param username
     * @param password
     */
    static String doLogin(String username,String password){
       //1.检验数据的合法性(判定用户名,密码是否为空,密码的长度,是否有数字字母特殊符号构成)
       if(username==null||"".equals(username))
           throw new IllegalArgumentException("用户不能为空");
       //2.基于用户名查询用户信息,并判定密码是否正确
       if(!"jack".equals(username))
           throw new RuntimeException("此用户不存在");
       if(!"123456".equals(password))
           throw new RuntimeException("密码不正确");
       //3.用户存在且密码正确,将用户信息写入到redis
        Jedis jedis = JedisDataSource.getConnection();
        String token= UUID.randomUUID().toString();
        jedis.hset(token, "username", username);
        jedis.hset(token, "permission", "sys:resource:create");
        jedis.expire(token, 10);//设置key的有效时间
        jedis.close();
       //4.将token返回给客户端(将来使用response对象响应到客户端).
        return token;
    }
    static String token;

    /**
     * 演示资源访问过程
     * 1)允许匿名访问(无需登录)
     * 2)登录后访问(认证通过了)
     * 3)登录后必须有权限才可以访问
     */
    static Object doGetResource(String token){
        //1.校验token是否为空
        if(token==null)
            throw new IllegalArgumentException("请先登录");
        //2.基于token查询redis数据,假如有对应数据说明用户登录了
        //方式一Jedis jedis=new Jedis("192.168.126.128", 6379);
        Jedis jedis = JedisDataSource.getConnection();
        String username=jedis.hget(token, "username");
        if(username==null)
            throw new RuntimeException("登录超时,请重新登录");
        String permission=jedis.hget(token, "permission");
        jedis.close();
        //3.检查用户是否有访问资源的权限,假如有则允许访问
        if(!"sys:resource:create".equals(permission))
            throw new RuntimeException("你没有权限访问这个资源");
        //4.返回要访问的资源.
        return "访问资源成功!";
    }
    public static void main(String[] args) {
        //1.登录操作(用户身份认证)
        token=doLogin("jack", "123456");
        System.out.println(token);
        //2.携带token访问资源服务器
        Object result=doGetResource(token);
        System.out.println(result);
    }
}

简易投票系统

在很多系统中设计中,都会有一个活动设计,开启一个活动之前,可以对这个活动的支持力度先进行一个调查,例如基于这个活动设计一个投票系统,例如:

shiro 单点登陆 配合redis 单点登录使用redis_redis_02

package com.jt;

import com.jt.JedisDataSource;
import redis.clients.jedis.Jedis;

import java.util.Set;

/**
 * 基于某个活动的简易投票系统设计
 * 1)投票数据存储到redis (key为活动id,多个用户id的集合)
 * 2)同一个用户不能执行多次投票
 * 3)具体业务操作(投票,获取总票数,检查是否投过票,取消投票,获取哪些人参与了投票)
 */
public class VoteDemo01 {

    /**
     * 获取哪些人执行了这个活动的投票
     * @param activityId
     * @return
     */
    static  Set<String> doGetMembers(String activityId){
        //1.建立连接
        Jedis jedis = JedisDataSource.getConnection();
        //2.获取当前活动的总票数
        Set<String> smembers = jedis.smembers(activityId);
        //3.释放资源
        jedis.close();
        return smembers;
    }
    /**
     * 获取指定活动的投票总数
     * @param activityId
     * @return
     */
    static Long doCount(String activityId){
        //1.建立连接
        Jedis jedis = JedisDataSource.getConnection();
        //2.获取当前活动的总票数
        Long count=jedis.scard(activityId);
        //3.释放资源
        jedis.close();
        return count;
    }
    /**
     * 执行投票操作
     * @param activityId
     * @param userId
     */
    static void doVote(String activityId,String userId){
        //1.建立连接
        Jedis jedis = JedisDataSource.getConnection();
        //2.执行投票
        //2.1检查是否投过票
        Boolean flag = jedis.sismember(activityId, userId);
        //2.2执行投票或取消投票
        if(flag){
            //假如已经投过票,再投票就取消投票
            jedis.srem(activityId, userId);
        }else{
            //没有投过票则执行投票
            jedis.sadd(activityId, userId);
        }
        //3.释放资源
        jedis.close();
    }
    public static void main(String[] args) {
        String activityId="101";
        String userId1="1";
        String userId2="2";
        String userId3="3";
        //执行投票动作
        doVote(activityId, userId1);
        doVote(activityId, userId2);
        doVote(activityId, userId3);
        //获取投票的总票数
        Long aLong = doCount(activityId);
        System.out.println("投票总数:"+aLong);
        //获取参与投票的成员
        Set<String> members= doGetMembers(activityId);
        System.out.println("投票人数:"+members);
    }

}