Auth.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <?php
  2. /**
  3. *-------------------------------------------------------------------------s*
  4. * 用户信息自动维护
  5. *-------------------------------------------------------------------------h*
  6. * @copyright Copyright (c) 2025-2099 Shopwwi Inc. (http://www.shopwwi.com)
  7. *-------------------------------------------------------------------------o*
  8. * @license http://www.shopwwi.com s h o p w w i . c o m
  9. *-------------------------------------------------------------------------p*
  10. * @link http://www.shopwwi.com
  11. *-------------------------------------------------------------------------w*
  12. * @since shopwwi
  13. *-------------------------------------------------------------------------w*
  14. */
  15. namespace Shopwwi\WebmanAuth;
  16. use Shopwwi\WebmanAuth\Exception\JwtTokenException;
  17. use Shopwwi\WebmanAuth\Facade\JWT as JwtFace;
  18. use Shopwwi\WebmanAuth\Facade\Str;
  19. class Auth
  20. {
  21. /**
  22. * 未携带 token 报错
  23. * @var bool
  24. */
  25. protected $fail = false;
  26. /**
  27. * 自定义角色
  28. * @var string
  29. */
  30. protected $guard = 'user';
  31. /**
  32. * 配置信息
  33. * @var array|mixed
  34. */
  35. protected $config = [];
  36. /**
  37. * token过期时间
  38. * @var int
  39. */
  40. protected $accessTime = 0;
  41. protected $refreshTime = 0;
  42. /**
  43. * 构造方法
  44. * @access public
  45. */
  46. public function __construct()
  47. {
  48. $_config = config('plugin.shopwwi.auth.app');
  49. if (empty($_config)) {
  50. throw new JwtTokenException('The configuration file is abnormal or does not exist');
  51. }
  52. $this->config = $_config;
  53. }
  54. /**
  55. * 设置当前角色
  56. * @param string $name
  57. * @return $this
  58. */
  59. public function guard(string $name):Auth
  60. {
  61. $this->guard = $name;
  62. return $this;
  63. }
  64. public function isThinkOrm()
  65. {
  66. $database = config('database');
  67. if (isset($database['default']) && strpos($database['default'], 'plugin.') === 0) {
  68. $database = false;
  69. }
  70. $thinkorm = config('thinkorm');
  71. if (isset($thinkorm['default']) && strpos($thinkorm['default'], 'plugin.') === 0) {
  72. $thinkorm = false;
  73. }
  74. return !$database && $thinkorm;
  75. }
  76. /**
  77. * 单独设定token过期时间
  78. * @param int $num
  79. * @return $this
  80. */
  81. public function accessTime(int $num): Auth
  82. {
  83. $this->accessTime = $num;
  84. return $this;
  85. }
  86. /**
  87. * 单独设定刷新token过期时间
  88. * @param int $num
  89. * @return $this
  90. */
  91. public function refreshTime(int $num): Auth
  92. {
  93. $this->refreshTime = $num;
  94. return $this;
  95. }
  96. /**
  97. * 输出报错
  98. * @param bool $error
  99. * @return Auth
  100. */
  101. public function fail(bool $error = true): Auth
  102. {
  103. $this->fail = $error;
  104. return $this;
  105. }
  106. /**
  107. * 登入信息自动验证
  108. * @param array $data
  109. * @return false|mixed
  110. */
  111. public function attempt(array $data)
  112. {
  113. try {
  114. if(is_array($data)) {
  115. list($model,$orm) = $this->getUserClass();
  116. if($model == null) throw new JwtTokenException('模型不存在',400);
  117. foreach ($data as $key=>$val){
  118. if($key !== 'password'){
  119. $model = $model->where($key,$val);
  120. }
  121. }
  122. if($orm == 'thinkphp'){
  123. $model = $model->find();
  124. }else{
  125. $model = $model->first();
  126. }
  127. if($model != null){
  128. if(isset($data['password'])){
  129. if(!password_verify($data['password'],$model->password)){
  130. throw new JwtTokenException('密码错误',400);
  131. }
  132. }
  133. return $this->login($model);
  134. }
  135. throw new JwtTokenException('账号或密码错误',400);
  136. }
  137. throw new JwtTokenException('数据类型不正确',400);
  138. }catch (JwtTokenException $e){
  139. if($this->fail){
  140. throw new JwtTokenException($e->getMessage(),$e->getCode());
  141. }
  142. return false;
  143. }
  144. }
  145. /**
  146. * 获取用户模型
  147. * @return mixed|null
  148. */
  149. protected function getUserClass(){
  150. $guardConfig = $this->config['guard'][$this->guard]['model'];
  151. $orm = 'laravel';
  152. $class = null;
  153. if(!empty($guardConfig)){
  154. if(is_array($guardConfig)){
  155. $orm = $guardConfig[1];
  156. $class = $guardConfig[0];
  157. }else{
  158. $class = $guardConfig;
  159. }
  160. }
  161. return [new $class,$orm];
  162. }
  163. /**
  164. * 获取会员信息
  165. * @return mixed|null
  166. */
  167. public function user($cache = false)
  168. {
  169. try {
  170. $key = $this->config['guard'][$this->guard]['key']; //获取主键
  171. $extend = JwtFace::guard($this->guard)->getTokenExtend();
  172. if(isset($extend->extend) && !empty($extend->extend) && isset($extend->extend->$key)){
  173. if($cache){
  174. return $extend->extend;
  175. }else{
  176. list($model,$orm) = $this->getUserClass();
  177. if($orm == 'thinkphp'){
  178. return $model->where($key,$extend->extend->$key)->find();
  179. }else{
  180. return $model->where($key,$extend->extend->$key)->first();
  181. }
  182. }
  183. }
  184. throw new JwtTokenException('配置信息异常',401);
  185. }catch (JwtTokenException $e){
  186. if($this->fail){
  187. throw new JwtTokenException($e->getMessage(),$e->getCode());
  188. }
  189. return null;
  190. }
  191. }
  192. /**
  193. * 登入并获取Token
  194. * @param $data
  195. */
  196. public function login($data)
  197. {
  198. $fields = $this->config['guard'][$this->guard]['field']; //允许使用的数据
  199. $idKey = $this->config['guard'][$this->guard]['key']; //获取主键
  200. $newData = [];
  201. // 过滤存储数据
  202. if(is_object($data)){
  203. foreach ($fields as $key){
  204. $newData[$key] = $data->$key ?? null;
  205. }
  206. }elseif(is_array($data) && count($data) > 0){
  207. foreach ($fields as $key){
  208. $newData[$key] = $data[$key] ?? null;
  209. }
  210. }
  211. try {
  212. if(!isset($newData[$idKey])){
  213. throw new JwtTokenException('缺少必要主键',400);
  214. }
  215. return JwtFace::guard($this->guard)->make($newData,$this->accessTime,$this->refreshTime);
  216. }catch (JwtTokenException $e){
  217. if($this->fail){ //当设定自动报错
  218. throw new JwtTokenException($e->getError(),$e->getCode());
  219. }
  220. return null;
  221. }
  222. }
  223. /**
  224. * 刷新令牌
  225. * @return false|JWT
  226. */
  227. public function refresh()
  228. {
  229. try {
  230. return JwtFace::guard($this->guard)->refresh($this->accessTime);
  231. }catch (JwtTokenException $e){
  232. if($this->fail){ //当设定自动报错
  233. throw new JwtTokenException($e->getError(),$e->getCode());
  234. }
  235. return false;
  236. }
  237. }
  238. /**
  239. * 退出登入
  240. */
  241. public function logout($all = false)
  242. {
  243. try {
  244. return JwtFace::guard($this->guard)->logout($all);
  245. }catch (JwtTokenException $e){
  246. if($this->fail){ //当设定自动报错
  247. throw new JwtTokenException($e->getError(),$e->getCode());
  248. }
  249. return false;
  250. }
  251. }
  252. /**
  253. * 生成JWT密钥
  254. * @return void
  255. * @throws \Exception
  256. */
  257. public function jwtKey()
  258. {
  259. }
  260. /**
  261. * 加密密码
  262. * @param $password
  263. * @return string|null
  264. */
  265. public function bcrypt($password): ?string
  266. {
  267. $key = config('plugin.shopwwi.auth.app.app_key');
  268. if (Str::startsWith($key, 'base64:')) {
  269. $key = base64_decode(substr($key, 7));
  270. }
  271. $hash = password_hash($password, PASSWORD_BCRYPT, [
  272. 'cost' => $key,
  273. ]);
  274. if ($hash === false) {
  275. throw new JwtTokenException('Bcrypt hashing not supported.');
  276. }
  277. return $hash;
  278. }
  279. /**
  280. * 动态方法 直接调用is方法进行验证
  281. * @access public
  282. * @param string $method 方法名
  283. * @param array $args 调用参数
  284. * @return bool
  285. */
  286. public function __call(string $method, array $args)
  287. {
  288. if ('is' == strtolower(substr($method, 0, 2))) {
  289. $method = substr($method, 2);
  290. }
  291. $args[] = lcfirst($method);
  292. return call_user_func_array([$this, 'is'], $args);
  293. }
  294. }