sso单点登录系统

喜你入骨 提交于 2019-11-30 08:39:09

sso单点登录概念

1.一处登录,处处登录.会单独做一个单点登录系统,只负责颁发token和验证token,和页面登录功能.

2.通过在浏览器cookie中放入token,和在redis中对应token放入用户信息的方式,代替session共享,使用jwt(json web token)自定义一个携带用户信息token加密算法.

3.cookie中的token是已经使用过的token,取名oldToken . url地址栏中的token新颁发的token,取名newToken

做法:

1.首先自定义一个注解,作用在方法上.有3种状态:

1.1 如果为null,表示直接放行,例如商品详情页,用户可以不用登录直接访问.

1.2 如果为false,经常用在购物车方法上,表示可登录可不登录,用户不登录购物车数据保存cookie中,用户登录数据保存数据库并放redis一份.

1.3 如果为true,表示用户必须登录,例如购物车结算跳订单页面.

 

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {

 

  boolean isNeededSuccess() default true;

 

}

 

 

 

 

2.自定义拦截器,并加入到springr容器中

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
  @Autowired
  AuthInterceptor authInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry){
    registry.addInterceptor(authInterceptor).addPathPatterns("/**");
    super.addInterceptors(registry);
  }
}

 

@Componentpublic class AuthInterceptor extends HandlerInterceptorAdapter {    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        HandlerMethod hm = (HandlerMethod)handler;        LoginRequired methodAnnotation = hm.getMethodAnnotation(LoginRequired.class);        if(methodAnnotation==null){            return true;        }else{            // 先获得用户cookie中关于用户的身份token            //token有四种情况            String token = "";            String oldToken = CookieUtil.getCookieValue(request, "oldToken", true);            if(StringUtils.isNotBlank(oldToken)){                token = oldToken;            }            String newToken = request.getParameter("newToken");            if(StringUtils.isNotBlank(newToken)){                token = newToken;            }            if(StringUtils.isNotBlank(token)){                // 验证用户的token是否正确                // 通过远程ws请求认证中心,验证token                String requestUrl = "http://passport.gmall.com:8090/verify?token="+token+"&currentIp="+request.getRemoteAddr();                String successJSON = HttpclientUtil.doGet(requestUrl);                HashMap<String,String> hashMap = new HashMap<>();                HashMap hashMapJSON = JSON.parseObject(successJSON, hashMap.getClass());                if(hashMapJSON!=null&&hashMapJSON.get("success").equals("success")){                    // 重新更新cookie的过期时间                    CookieUtil.setCookie(request,response,"oldToken",token,60*60,true);                    request.setAttribute("memberId",hashMapJSON.get("memberId"));                    request.setAttribute("nickname",hashMapJSON.get("nickname"));                    return true;                }else{                    if(methodAnnotation.isNeededSuccess()){                        String ReturnUrl = request.getRequestURL().toString();                        response.sendRedirect("http://passport.gmall.com:8090/index?ReturnUrl="+ReturnUrl);                        // 拦截验证                        return false;                    }                }            }else{                if(methodAnnotation.isNeededSuccess()) {                    String ReturnUrl = request.getRequestURL().toString();                    response.sendRedirect("http://passport.gmall.com:8090/index?ReturnUrl=" + ReturnUrl);                    // 拦截验证                    return false;                }            }        }        return true;    }}3.单点登录系统代码
@Controllerpublic class passportController {    @ReferenceUserService userService;@RequestMapping("vlogin")    public String vlogin(String code, HttpServletRequest request) {        // 换取access_tokenString access_token_url = "https://api.weibo.com/oauth2/access_token?client_id= 25920146&client_secret=dc8de1392f642a01259b136ff8e970b9&grant_type=authorization_code&redirect_uri=http://passport.gmall.com:8090/vlogin&code=e211655dd6c78a66fcfcfdff552424f6";Map<String,String> map = new HashMap<String,String>();map.put("client_id","25920146");map.put("client_secret","dc8de1392f642a01259b136ff8e970b9");map.put("grant_type","authorization_code");map.put("redirect_uri","http://passport.gmall.com:8090/vlogin");map.put("code",code);String access_json = HttpclientUtil.doPost("https://api.weibo.com/oauth2/access_token", map);System.out.println(access_json);Map<String,String> map_access_json =  new HashMap<String,String>();Map access_map = JSON.parseObject(access_json, map_access_json.getClass());// 获得第三方用户数据String access_token = (String)access_map.get("access_token");String uid = (String)access_map.get("uid");// uid uidStrUmsMember umsMember = new UmsMember();umsMember = userService.isUidExists(uid);        if(umsMember==null){            String show_url = "https://api.weibo.com/2/users/show.json?access_token="+access_token+"&uid="+uid;String user_json = HttpclientUtil.doGet(show_url);Map<String,String> map_user_json =  new HashMap<String,String>();Map user_map = JSON.parseObject(user_json, map_user_json.getClass());System.out.println(user_map);// 存入数据库umsMember.setNickname((String)user_map.get("screen_name"));umsMember.setUsername((String)user_map.get("name"));umsMember.setSourceType("2");umsMember.setSourceUid((String)user_map.get("idstr"));umsMember.setCreateTime(new Date());umsMember.setAccessToken(access_token);umsMember.setAccessCode(code);umsMember = userService.addUser(umsMember);}        // 根据用户信息生成tokenString key = "houruisso";String ip = request.getRemoteAddr();Map<String,Object> token_map = new HashMap<>();token_map.put("nickname",umsMember.getNickname());token_map.put("memberId",umsMember.getId());String token = JwtUtil.encode(key, token_map, ip);// 将生成的token和登录用户信息保存在缓存中一分userService.addUserCache(token,umsMember);        return "redirect:http://search.gmall.com:8083/index?newToken="+token;}    @RequestMapping("login")    @ResponseBody    public String login(UmsMember umsMember, HttpServletRequest request) {        System.out.println("用户登录,验证用户名和密码是否正确");// 调用用户服务userService,验证用户名和密码UmsMember umsMemberFromDb = userService.login(umsMember);        if (umsMemberFromDb == null) {            return "fail";} else {            // 根据已经登录的用户信息和,服务器密钥,和其他盐值(根据系统算法)生成一个tokenString key = "atguigusso";String ip = request.getRemoteAddr();//String ip = request.getHeader("x-forward-for");//nginxMap<String, Object> map = new HashMap<>();map.put("nickname", umsMemberFromDb.getNickname());map.put("memberId", umsMemberFromDb.getId());String token = JwtUtil.encode(key, map, ip);// 将生成的token和登录用户信息保存在缓存中一分userService.addUserCache(token,umsMemberFromDb);            return token;}    }    @RequestMapping("verify")    @ResponseBody    public String verify(String token, String currentIp) {        System.out.println("认证中心认证用户的token");String key = "houruisso";String ip = currentIp;Map<String, Object> map = JwtUtil.decode(token, key, ip);Map<String,String> verifyReturn = new HashMap<>();        if (map != null) {            verifyReturn.put("success","success");verifyReturn.put("memberId",(String)map.get("memberId"));verifyReturn.put("nickname",(String)map.get("nickname"));            return JSON.toJSONString(verifyReturn);} else {            verifyReturn.put("success","fail");            return JSON.toJSONString(verifyReturn);}    }    @RequestMapping("index")    public String index(String ReturnUrl, ModelMap modelMap) {        System.out.println("认证中心首页");modelMap.put("ReturnUrl", ReturnUrl);        return "index";}}
4.前端代码
<!--底部--><input type="text" id="ReturnUrl"  th:value="${ReturnUrl}"/><br /></body><script language="JavaScript">        function submitLogin() {        var username = $("#username").val();        var password = $("#password").val();        $.post("login",{username:username,password:password},function(token){        if(token=="fail"){        alert("登录失败,用户名和密码错误");        }else{        window.location.href=$("#ReturnUrl").val()+"?newToken="+token;        }        });        }

@Overridepublic void addUserCache(String token, UmsMember umsMemberFromDb) {        String tokenKey = "user:"+umsMemberFromDb.getId()+":token";        String userKey = "user:"+umsMemberFromDb.getId()+":info";        Jedis jedis = null;        jedis = redisUtil.getJedis();        jedis.setex(tokenKey,60*60,token);        jedis.setex(userKey,60*60, JSON.toJSONString(umsMemberFromDb));        jedis.close();        }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!