码迷,mamicode.com
首页 > 其他好文 > 详细

实现 OAuth2.0 服务端

时间:2014-12-01 12:54:07      阅读:1391      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   io   ar   color   os   使用   

要实现OAuth服务端,我觉的就得先理解客户端的调用流程,服务提供商实现可能也有些区别,实现OAuth服务端的方式很多,具体可能看 http://oauth.net/code/

各语言的实现有(我使用了Apache Oltu):

  • Java
  • NodeJS
  • Ruby
  • .NET
  • 实现主要涉及参数配置如下:
    授权码设置(code)
    第三方通过code进行获取 access_token的时候需要用到,code的超时时间为10分钟,一个code只能成功换取一次access_token即失效。
    授权作用域(scope)
    作用域代表用户授权给第三方的接口权限,第三方应用需要向服务端申请使用相应scope的权限后,经过用户授权,获取到相应access_token后方可对接口进行调用。
    令牌有效期(access_token)
    access_token是调用授权关系接口的调用凭证,由于access_token有效期(目前为2个小时)较短,当access_token超时后,可以使用refresh_token进行刷新,access_token刷新结果有两种:
        1. 若access_token已超时,那么进行refresh_token会获取一个新的access_token,新的超时时间;
        2. 若access_token未超时,那么进行refresh_token不会改变access_token,但超时时间会刷新,相当于续期access_token。
    refresh_token拥有较长的有效期(30天),当refresh_token失效的后,需要用户重新授权。

    请求授权码

    /**
     * Authorization Code 授权码模式
     * Created by Irving on 2014/11/22.
     * Impl OAth2  http://oauth.net/2/
     */
    @Controller
    @RequestMapping("/oauth2")
    public class AuthzController {
        private static Logger logger = LoggerFactory.getLogger(AuthzController.class);
        private Cache cache ;
        @Autowired
        public AuthzController(CacheManager cacheManager) {
            this.cache = cacheManager.getCache("oauth2-cache");
        }
         /* *
         * 构建OAuth2授权请求 [需要client_id与redirect_uri绝对地址]
         * @param request
         * @param session
         * @param model
         * @return 返回授权码(code)有效期10分钟,客户端只能使用一次[与client_id和redirect_uri一一对应关系]
         * @throws OAuthSystemException
         * @throws IOException
         * @url  http://localhost:8080/oauth2/authorize?client_id={AppKey}&response_type=code&redirect_uri={YourSiteUrl}
         * @test http://localhost:8080/oauth2/authorize?client_id=fbed1d1b4b1449daa4bc49397cbe2350&response_type=code&redirect_uri=http://baidu.comx
         */
        @RequestMapping(value = "/authorize")
        public String authorize(HttpServletRequest request,HttpSession session,Model model)
                throws OAuthSystemException, IOException {
            try {
                //构建OAuth请求
                OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);
                //验证redirecturl格式是否合法 (8080端口测试)
                if (!oauthRequest.getRedirectURI().contains(":8080")&&!Pattern.compile("^[a-zA-Z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\s*)?$").matcher(oauthRequest.getRedirectURI()).matches()) {
                    OAuthResponse oauthResponse = OAuthASResponse
                                                  .errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
                                                  .setError(OAuthError.CodeResponse.INVALID_REQUEST)
                                                  .setErrorDescription(OAuthError.OAUTH_ERROR_URI)
                                                  .buildJSONMessage();
                    logger.error("oauthRequest.getRedirectURI() : " + oauthRequest.getRedirectURI() + " oauthResponse.getBody() : " + oauthResponse.getBody());
                    model.addAttribute("errorMsg", oauthResponse.getBody());
                    return "/oauth2/error";
                }
                //验证appkey是否正确
                if (!validateOAuth2AppKey(oauthRequest)){
                    OAuthResponse oauthResponse = OAuthASResponse
                                                  .errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
                                                  .setError(OAuthError.CodeResponse.ACCESS_DENIED)
                                                  .setErrorDescription(OAuthError.CodeResponse.UNAUTHORIZED_CLIENT)
                                                  .buildJSONMessage();
                    logger.error("oauthRequest.getRedirectURI() : "+oauthRequest.getRedirectURI()+" oauthResponse.getBody() : "+oauthResponse.getBody());
                    model.addAttribute("errorMsg", oauthResponse.getBody());
                    return "/oauth2/error";
                }
                //查询客户端Appkey应用的信息
                String clientName= "Just Test App";//oauthClientService.findByClientId(oauthRequest.getClientId());
                model.addAttribute("clientName",clientName);
                model.addAttribute("response_type",oauthRequest.getResponseType());
                model.addAttribute("client_id",oauthRequest.getClientId());
                model.addAttribute("redirect_uri",oauthRequest.getRedirectURI());
                model.addAttribute("scope",oauthRequest.getScopes());
                //验证用户是否已登录
                if(session.getAttribute(ConstantKey.MEMBER_SESSION_KEY)==null) {
                    //用户登录
                    if(!validateOAuth2Pwd(request)) {
                        //登录失败跳转到登陆页
                        return "/oauth2/login";
                    }
                }
                //判断此次请求是否是用户授权
                if(request.getParameter("action")==null||!request.getParameter("action").equalsIgnoreCase("authorize")){
                    //到申请用户同意授权页
                    return "/oauth2/authorize";
                }
               //生成授权码 UUIDValueGenerator OR MD5Generator
               String authorizationCode = new OAuthIssuerImpl(new MD5Generator()).authorizationCode();
               //把授权码存入缓存
               cache.put(authorizationCode, DigestUtils.sha1Hex(oauthRequest.getClientId()+oauthRequest.getRedirectURI()));
               //构建oauth2授权返回信息
               OAuthResponse oauthResponse = OAuthASResponse
                                             .authorizationResponse(request,HttpServletResponse.SC_FOUND)
                                             .setCode(authorizationCode)
                                             .location(oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI))
                                             .buildQueryMessage();
               //申请令牌成功重定向到客户端页
               return "redirect:"+oauthResponse.getLocationUri();
            } catch(OAuthProblemException ex) {
                OAuthResponse oauthResponse = OAuthResponse
                                              .errorResponse(HttpServletResponse.SC_UNAUTHORIZED)
                                              .error(ex)
                                              .buildJSONMessage();
                logger.error("oauthRequest.getRedirectURI() : " + ex.getRedirectUri() + " oauthResponse.getBody() : " + oauthResponse.getBody());
                model.addAttribute("errorMsg", oauthResponse.getBody());
                return  "/oauth2/error";
            }
        }
    
        /**
         * 用户登录
         * @param request
         * @return
         */
        private boolean validateOAuth2Pwd(HttpServletRequest request) {
            if("get".equalsIgnoreCase(request.getMethod())) {
                return false;
            }
            String name = request.getParameter("name");
            String pwd = request.getParameter("pwd");
            if(StringUtils.isEmpty(name) || StringUtils.isEmpty(pwd)) {
                return false;
            }
            try {
                if(name.equalsIgnoreCase("Irving")&&pwd.equalsIgnoreCase("123456")){
                    //登录成功
                    request.getSession().setAttribute(ConstantKey.MEMBER_SESSION_KEY,"Irving");
                    return true;
                }
                return false;
            } catch (Exception ex) {
                logger.error("validateOAuth2Pwd Exception: " + ex.getMessage());
                return false;
            }
        }
    
        /**
         * 验证ClientID 是否正确
         * @param oauthRequest
         * @return
         */
        public boolean validateOAuth2AppKey(OAuthAuthzRequest oauthRequest) {
            //客户端Appkey
            ArrayList arrayKeys = new  ArrayList();
            arrayKeys.add("fbed1d1b4b1449daa4bc49397cbe2350");
            arrayKeys.add("a85b033590714fafb20db1d11aed5497");
            arrayKeys.add("d23e06a97e2d4887b504d2c6fdf42c0b");
            return arrayKeys.contains(oauthRequest.getClientId());
        }
    }

    Refer:https://open.weixin.qq.com/cgi-bin/readtemplate?t=resource/app_wx_login_tmpl&lang=zh_CN#faq

    实现 OAuth2.0 服务端

    标签:des   style   blog   http   io   ar   color   os   使用   

    原文地址:http://www.cnblogs.com/Irving/p/4134752.html

    (0)
    (0)
       
    举报
    评论 一句话评论(0
    登录后才能评论!
    © 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
    迷上了代码!