当前位置:   article > 正文

spring security 安全框架改造统一登录oauth2.0方式_security多系统统一登陆

security多系统统一登陆

继上次改造统一登录之后,这次又接到改造任务,这次的项目结构略有不同,不再有web.xml文件,也不是集成的含有拦截器的jar包,而是oauth2.0的授权码(CODE)方式的认证流程

因为前端还是vue,所以也让前端同事帮忙改了一些,

首先是,摒弃我们的登录页面,vue项目启动的时候,自动跳转到统一登录页(http://[ip]:[port]/[server_appname]/oauth2/authorize?client_id=[client_id]&response_type=code&redirect_uri=[redirect_uri]这里需要说明下,跳转登录页的路径是统一登录平台提供的,当然参数client_id也是对方给分配的response_code=code是固定值,redirect_uri是回调路径),在统一登录页面输入用户名和密码,点击登录,统一登录平台负责校验账号和密码,完成后,会返回给你这边一个code,并执行回调路径打开我们的登录页(也可以不打开页面,就算打开也是为了拿到code,然后立马发送获取token的请求),然后我们拿着code去统一登录端换取token,(http://[ip]:[port]/[server_appname]/oauth2/access_token?client_id=[client_id]&client_secret=[client_secret]&grant_type=authorization_code&code=[code]&redirect_uri=[redirect_uri]client_secret也是统一登录平台给分配的,就是这一步,要根据实际项目需要看是前端直接请求,还是让后端帮忙转发,后端转发的好处是,后端可以先拿到返回的token,然后再根据token获取用户信息,包括权限,然后返回前端,这样做就会有一个问题,你以后每次访问某个页面,spring security框架都会拦截你的请求,检查是否有token,假如有token,还会比较跟用户信息能不能对应上,因为统一平台返回的token,在我们系统的application中跟用户没有绑定,所以就不能访问成功。)

后来我们是这样处理的,拿到统一平台的token后,紧接着去统一平台获取用户信息

http://[ip]:[port]/[server_appname]/oauth2/introspect?access_token=[access_token])此地址由统一平台提供,获取用户信息后,我们拿着用户名再次我们系统的登录逻辑,此时的登录,仅仅是检查此用户是否在我们的系统中存在,存在则查询出详细信息,用详细信息封装成一个 spring security 需要的token,并存入整个后台应用上下文。返回登录成功,此时,在访问系统中的任何页面,也会判断请求是否有token,token跟用户信息是否匹配。下面是一是一些伪代码;

先配置一个不会拦截的路径,作用是在第二步,用code换取token是,前台请求这个路径,我后台再次转发请求

 然后前台的每次请求都去检查一下token

改善后如下:

@RequestMapping("/sso")
  public ResponseMessage loginAppWithLoginName( HttpServletRequest request) {
      try {

          String code = request.getParameter("code");

          CloseableHttpClient httpclient = HttpClients.createDefault();
          HttpGet tttpGet = new HttpGet("http://192.168.0.70:30017/oauth2/access_token?client_id=XhWXEp2UQkmMUvMJ3Qjf5Q&client_secret=GWWzr1UgQuqRyp_pDB3WPw" +
                  "&grant_type=authorization_code&code=" + code + "&redirect_uri=http://localhost:8089/#");// 创建httpPost

          CloseableHttpResponse response = null;

          response = httpclient.execute(tttpGet);
          StatusLine status = response.getStatusLine();
          int state = status.getStatusCode();
          if (state == HttpStatus.SC_OK) {
              HttpEntity responseEntity = response.getEntity();
              String jsonString = EntityUtils.toString(responseEntity);
              System.out.println(jsonString);
              JSONObject jsonObject = JSONObject.parseObject(jsonString);

              String token = jsonObject.getString("access_token");

              System.out.println("token---->>>" + token);

              String urlp = "http://192.168.0.70:30017/oauth2/user_info?access_token=" + token;

              System.out.println("urlp---->>>" + urlp);

              HttpGet tttpGet1 = new HttpGet(urlp);// 创建httpPo

              tttpGet1.setHeader("Accept", "application/json");
              // httpPost.setHeader("Content-Type", "application/json");
              // String charSet = "UTF-8";

              CloseableHttpClient httpclient1 = HttpClients.createDefault();
              CloseableHttpResponse response1 = null;
              response1 = httpclient1.execute(tttpGet1);
              StatusLine status1 = response1.getStatusLine();
              int state1 = status1.getStatusCode();
              if (state1 == HttpStatus.SC_OK) {
                  HttpEntity responseEntity1 = response1.getEntity();
                  String jsonString1 = EntityUtils.toString(responseEntity1);
                  System.out.println(jsonString1);
                  JSONObject jsonObject1 = JSONObject.parseObject(jsonString1);
                  String account = jsonObject1.getString("account");
                  System.out.println("account-->>>>>>>>>>>>>>" + account);


                  ResponseMessage responseMessage= InsiisCommBusinessSys.autologin(account, request);


                  return  responseMessage;
              }

          } else {
              return ResponseMessage.error("非法请求,未获取到用户信息");
          }

       /*String data=jo.get("data").toString();
       String signature=jo.get("signature").toString();
       if(SignUtils.checkSignature(signature, data)) {
          String decodedata=AesUtil.decrypt(data);
          JSONObject jsondata=JSONObject.parseObject(decodedata);

          //在这里拿到用户名,再次调用不需要密码的登录,产生自己的spring security 需要的token


          return InsiisCommBusinessSys.autologin(jsondata.getString(SignUtils.SIGN_DATA_EST), request);
       }else {
          return ResponseMessage.error("非法请求,未获取到用户信息");
       }
      }catch (Exception e) {
   return ResponseMessage.error("未获取到用户信息");
}*/
      }catch (Exception e){
          e.printStackTrace();
      }
      return ResponseMessage.error("未获取到用户信息");
  }

重点是autologin()方法生成spring security需要的token

public static ResponseMessage autologin(String loginname,HttpServletRequest request) {
     try {
        if(null==loginname||loginname.equals("")) {
           return ResponseMessage.error("登录用户名不能为空");
        }
         UserDetails userDetails = sysUserDetailsService.loadUserByUsername(loginname);


         Authentication token = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
         //((UsernamePasswordAuthenticationToken) token).setDetails(new WebAuthenticationDetails(request));

         UsernamePasswordAuthenticationFilter    to  =new UsernamePasswordAuthenticationFilter();

         to.setDetails(request,(UsernamePasswordAuthenticationToken)token);

     //  SecurityContextHolder.getContext().getAuthentication();
         SecurityContextHolder.getContext().setAuthentication(token);


         SysUserDetails sysUserDetails= (SysUserDetails)token.getPrincipal();


        String  tokens= JWT.create().withAudience(sysUserDetails.getUserid())
                 .sign(Algorithm.HMAC256(sysUserDetails.getPassword()));

         sysUserDetails.setEst(tokens);
         try {
            System.out.println("InsiisCommBusinessSys sessionid: "+request.getSession().getId()+",sessionMaxInterval:"+request.getSession().getMaxInactiveInterval()+"");
            System.out.println("单点登录"+sysUserDetails.getNickname()+"成功");
             SysLogonLog log = logService.saveLogonLog(SecurityUtils.getIpAddr(request),request.getSession().getId());
             sysUserDetails.getOthers().put("logid",log.getLogonlogid());
             sysUserDetails.getOthers().put("logontime",log.getLogontime());
             userService.clearFailNO(userDetails.getUsername());
         }catch (Exception e){
            System.out.println("单点登录失败"+loginname+e.getMessage());
            e.printStackTrace();
            return ResponseMessage.error("登录失败"+e.getMessage());
         }
         return ResponseMessage.ok("获取成功",sysUserDetails);
     } catch (Exception e) {
         return ResponseMessage.error("未获取到用户信息");
     }
}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/84297
推荐阅读
相关标签
  

闽ICP备14008679号