自己开发实现OAuth做webapi认证

看到园子里面有人写的OAuth,就想把自己实现的OAuth也分享一下,关于OAuth协议这里就不再赘述。

一、作为认证服务器,首先需要提供一个可以通过appid/appsecret来获取token这样的一个接口,于是便有了以下代码。

    public class AuthController : ApiController
    {
        [HttpGet]
        public HttpResponseMessage Token(string appid = "", string appsecret = "")
        {
            ApiResponseEntity rep;
            var isv = AppManage.Instance.GetAppISV(appid, appsecret);
            if (isv != null)
            {
                string token = TokenManage.Instance.CreateToken(appid);

                rep = new ApiResponseEntity
                {
                    Status = InterfaceStatus.Success,
                    BizData = new
                    {
                        AccessToken = token
                    }
                };
            }
            else
            {
                rep = new ApiResponseEntity()
                {
                    Status = InterfaceStatus.Parm_Missing,
                    Message = "param error"
                };
            }
            return rep.ToHttpResponseMessage();
        }
}
View Code

创建token的算法可以自行实现,我是将新生成的Guid做了一下md5处理,代码如下:

public string CreateToken(string appid)
        {
            string token = Guid.NewGuid().ToString().ToMd5();
            Set(token, appid);
            return token;
        }
View Code

上文可以看到,在生成token了以后,就一个SetToken,就是将token存储在缓存里面,并设置了一定时间的生存周期,代码如下:

public void Set(string token, string appid)
        {
            var config = ServerConfigManage.Instance.GetServerConfig();
            string key = string.Format(RedisCacheKey.App_Token, token);
            RedisNetHelper.Set<string>(key, appid, DateTime.Now.AddSeconds(config.TokenSurvivalTime));
        }
View Code

为什么要用token做key,是因为token的变更会导致isv token验证失效,但是用token做key就可以在存活周期内,这个key都可以使用,避免了多线程获取token,或是其他原因导致的token失效。作为认证服务器,还需要提供一个RefreshToken这样的接口,用来给刷新token的存活周期,代码相似这里就不再赘述。

 

二、在Api做验证的时候,就需要开始对Token进行验证了,代码如下:

 public class OAuthHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            ApiResponseEntity repEntity = null;
            string appid = "";
            string ip = RequestHelper.GetWebClientIp();
            if (!OAuthValidate.IpValidate(ip))
            {
                repEntity = new ApiResponseEntity
                {
                    Status = InterfaceStatus.IllegalIp,
                    Message = "ip access limit"
                };
            }
            else
            {
                string token = "";
                string url = request.RequestUri.AbsoluteUri;
                var routeData = request.GetRouteData();
                string controller = routeData.Values["controller"].ToString().ToLower();
                string action = routeData.Values["action"].ToString().ToLower();
                if (controller.Equals("auth") && action.Equals("token"))
                {
                    return base.SendAsync(request, cancellationToken);
                }

                if (request.Method == HttpMethod.Get)
                {
                    var query = request.RequestUri.ParseQueryString();
                    token = query["token"];
                }

                if (token == null || token.Length == 0)
                {
                    repEntity = new ApiResponseEntity
                    {
                        Status = InterfaceStatus.Token_Faild,
                        Message = "token invalid"
                    };
                }
                else
                {
                    appid = TokenManage.Instance.Get(token);
                    if (appid == null || appid.Length == 0)
                    {
                        repEntity = new ApiResponseEntity
                        {
                            Status = InterfaceStatus.Token_Faild,
                            Message = "token invalid"
                        };
                    }
                    else
                    {
                        if (!OAuthValidate.ApiValidate
                            (
                            string.Format("{0}/{1}", controller, action),
                            appid
                            ))
                        {
                            repEntity = new ApiResponseEntity
                            {
                                Status = InterfaceStatus.No_Access,
                                Message = "api access limit"
                            };
                        }
                    }
                }
            }

            if (repEntity != null)
            {
                var tsc = new TaskCompletionSource<HttpResponseMessage>();
                tsc.SetResult(repEntity.ToHttpResponseMessage());
                return tsc.Task;
            }
            else
            {
                return base.SendAsync(request, cancellationToken);
            }
        }
    }
View Code

使用比较传统的方式,继承于DelegatingHandler,然后进行处理,首先是做的IP验证,然后再进行token有效期验证,最后再进行Api的权限调用验证。验证的代码如下:

 public static bool IpValidate(string ip)
        {
            var config = ServerConfigManage.Instance.GetServerConfig();
            bool isPass = true;
            if (isPass && config.IsStartIpWhiteList)
            {
                isPass = config.IpWhiteList.Contains(ip);
            }
            if (isPass && config.IsStartIpBlackList)
            {
                isPass = !config.IpBlackList.Contains(ip);
            }
            return isPass;
        }

        public static bool ApiValidate(string api, string appid)
        {
            var config = ServerConfigManage.Instance.GetServerConfig();
            if (config.IsStartApiControl)
            {
                var apis = AppManage.Instance.GetAppApiResource(appid);
                return apis != null && apis.Contains(api);
            }
            return true;
        }
View Code

GetServerConfig()是从DB/Cache里面获取服务器的自定义配置,然后看是否开启ip白名单/黑名单,下面的代码同理,是否开启权限验证。

那认证服务器到这里实际上就结束了,关于isv申请appid/appsecret。然后用户同意授权以后,存储appid和user之间的关联关系,就需要看客自行实现了。

 

另外有一个扩展代码这里也提一下,就是关于ApiResponseEntity的返回值处理,代码如下:

public static HttpResponseMessage ToHttpResponseMessage(this ResponseEntity rep, bool isEncrypt = false)
        {
            return new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent
                    (
                    isEncrypt
                    ? EncryptHelper.Base64Replace(EncryptHelper.AESEncryptBase64(JsonHelper.ToJson(rep), Config.ApiEncryptKey))
                    : JsonHelper.ToJson(rep), 
                    System.Text.Encoding.UTF8,
                    "application/json"
                    )
            };
        }
View Code

 

转载于:https://www.cnblogs.com/selfteam/p/4923098.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot是一个开源的Java开发框架,用于构建独立的、可扩展的、基于Spring的应用程序。Spring Security是一个为Java应用程序提供身份认证和授权的框架,它提供了许多安全功能,如用户认证、角色管理和资源访问控制。OAuth2是一种用于授权的开放标准,它允许应用程序通过第三方身份验证服务器来获取访问令牌,以便访问受保护的资源。 要集成Spring Security OAuth2到Spring Boot 3.0的Web API中,需要以下步骤: 1. 添加依赖:在项目的pom.xml文件中添加Spring Security OAuth2的依赖。例如,可以添加以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> ``` 2. 配置Spring Security:创建一个配置类,扩展`WebSecurityConfigurerAdapter`,并重`configure`方法来配置Spring Security。你可以定义用户认证方式和角色管理等配置。 3. 配置OAuth2:创建一个配置类,扩展`WebSecurityConfigurerAdapter`,并重`configure`方法。在方法中配置OAuth2的相关信息,如认证服务器URL、客户端ID、客户端密码等。 4. 创建资源服务器:创建一个类,注解为`@RestController`,用于提供Web API接口。在方法上使用`@PreAuthorize`注解定义接口的访问权限。 通过以上步骤,你可以将Spring Boot 3.0的Web API和Spring Security OAuth2集成起来。这样,你的应用程序将具有身份认证、角色管理和资源访问控制的功能,并可以使用OAuth2来授权访问受保护的资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值