SSO认证中心

发布时间 2023-08-16 16:37:53作者: 咔咔皮卡丘

参考文献

https://blog.csdn.net/u011277123/article/details/53404269

如有侵权,请联系删除

前言

  在做项目过程中,可能会遇到客户想要做统一认证,但又没有过多的预算。在这种情况下,只能提取统一认证中的精华部门,实现一个简易的单点登录。本文主要介绍基于session实现的跨域名的单点登录demo及统一认证服务需要拥有哪些功能。源码:https://gitee.com/learning_demo/sso_demo 

功能

登录功能

登录功能中,我们要实现1.登录页面;2.登录接口;

 1.登录页面

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>登录</title>
</head>


<body>
    <div>
        <form th:action="@{/login}" method="POST">
            <input type="text" name="returnUrl" th:value="${returnUrl}"/>
            <input type="text" name="appName"  th:value="${appName}"/>
            <input type="text" name="username"/>
            <input type="text" name="password"/>
            <button  type="submit">登录</button>
        </form>
    </div>
</body>

</html>

2.登录接口

@PostMapping("/login")
    public String login(HttpServletRequest request,String username,String password,String returnUrl,String appName,RedirectAttributes attr){

        if(Const.USERNAME.equals(username)&&Const.PASSWORD.equals(password)){

            //登录成功
            // 1、生成token,设置session
            String token = CodecUtil.createUUID();
            HttpSession session = request.getSession();
            String id = session.getId();
            log.info("/login,SessionId="+id);
            session.setAttribute("isLogin", true);
            session.setAttribute("token",token);

            // 2、将应用名注册到认证中心
            List<String> appNameList = new ArrayList<>();
            appNameList.add(appName);
            String appNameStr = JSON.toJSONString(appNameList);
            RedisService.setex(Const.TOKEN_PREFIX+token, appNameStr, Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
            attr.addAttribute("token", token);

            return "redirect:"+returnUrl;
        }else{
            attr.addAttribute("returnUrl", returnUrl);
            attr.addAttribute("appName", appName);
            return "redirect:/login";
        }
    }

    @GetMapping("/login")
    public String loginPage(HttpServletRequest request,Model model,RedirectAttributes attr){

        String returnUrl = request.getParameter("returnUrl");
        String appName = request.getParameter("appName");

       HttpSession session = request.getSession();
        String id = session.getId();
        log.info("/login,SessionId="+id);
        Boolean isLogin = (Boolean)session.getAttribute("isLogin");
        String token = (String)session.getAttribute("token");
        if(isLogin!=null&&isLogin){
            //返回token
            attr.addAttribute("token",token);
            return "redirect:"+returnUrl;
        }
        model.addAttribute("returnUrl",returnUrl);
        model.addAttribute("appName",appName);
        return "login";
    }

 

验证功能

@PostMapping("/verified")
    @ResponseBody
    public Object verified(HttpServletRequest request){

        String token = request.getParameter("token");
        String appName = request.getParameter("appName");

        //验证
        String appNameStr = RedisService.get(Const.TOKEN_PREFIX + token);
        if(appNameStr!=null){
            List<String> appNameList = JSON.parseArray(appNameStr, String.class);
            if(!appNameList.contains(appName)){
                appNameList.add(appName);
            }
            appNameStr = JSON.toJSONString(appNameList);
            RedisService.setex(Const.TOKEN_PREFIX+token, appNameStr, Const.RedisCacheExtime.REDIS_SESSION_EXTIME);
            return "0000";
        }else{
            return "0001";
        }

    }

 

登出功能

更新中....

 

客户端令牌校验

public class AccessInterceptor extends HandlerInterceptorAdapter {
    Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        String token = request.getParameter("token");
        log.info("经过了令牌验证拦截器");
        log.info("token:" + token);

        String requestURL = request.getRequestURL().toString();

        //本地session
//        Boolean isLogin = (Boolean)request.getSession().getAttribute("isLogin");
//        if(isLogin!=null&&isLogin){
//           return true;
//        }

        //没有令牌,重定向到认证中心的登录页
        if(token==null){
            response.sendRedirect("http://www.sso.com:8080/login?returnUrl="+requestURL+"&appName=a");
            return false;
        }

        //验证令牌
        HashMap<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("appName", "a");
        String verifiedResult = HttpClientUtil.sendPost("http://www.sso.com:8080/verified", map);
        if(verifiedResult!=null&&"0000".equals(verifiedResult)){
            request.getSession().setAttribute("isLogin",true);
            return true;
        }else{
            //去登录
            response.sendRedirect("http://www.sso.com:8080/login?returnUrl="+requestURL+"&appName=a");
            return false;
        }
    }
}

注:客户端根据自身情况对接统一认证。