AbstractTokenGranter.java 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package jnpf.granter;
  2. import cn.dev33.satoken.context.SaHolder;
  3. import cn.dev33.satoken.stp.StpUtil;
  4. import cn.dev33.satoken.stp.parameter.SaLoginParameter;
  5. import jnpf.base.ActionResult;
  6. import jnpf.base.UserInfo;
  7. import jnpf.config.ConfigValueUtil;
  8. import jnpf.constant.MsgCode;
  9. import jnpf.consts.AuthConsts;
  10. import jnpf.consts.DeviceType;
  11. import jnpf.consts.LoginTicketStatus;
  12. import jnpf.exception.LoginException;
  13. import jnpf.exception.TenantDatabaseException;
  14. import jnpf.model.BaseSystemInfo;
  15. import jnpf.model.LoginTicketModel;
  16. import jnpf.model.logout.LogoutResultModel;
  17. import jnpf.model.tenant.TenantVO;
  18. import jnpf.service.LoginService;
  19. import jnpf.util.RedisUtil;
  20. import jnpf.util.TenantProvider;
  21. import jnpf.util.TicketUtil;
  22. import jnpf.util.UserProvider;
  23. import org.springframework.beans.factory.annotation.Autowired;
  24. import org.springframework.core.Ordered;
  25. import org.springframework.util.AntPathMatcher;
  26. import org.springframework.util.PathMatcher;
  27. import java.util.HashMap;
  28. import java.util.Map;
  29. import static jnpf.consts.AuthConsts.DEF_TENANT_DB;
  30. import static jnpf.consts.AuthConsts.DEF_TENANT_ID;
  31. /**
  32. *
  33. * @author JNPF开发平台组
  34. * @copyright 引迈信息技术有限公司
  35. */
  36. public abstract class AbstractTokenGranter implements TokenGranter, Ordered {
  37. @Autowired(required = false)
  38. protected LoginService loginService;
  39. @Autowired
  40. protected ConfigValueUtil configValueUtil;
  41. @Autowired
  42. protected RedisUtil redisUtil;
  43. protected static PathMatcher pathMatcher = new AntPathMatcher();
  44. private String authenticationUrl;
  45. public AbstractTokenGranter(String authenticationUrl){
  46. this.authenticationUrl = authenticationUrl;
  47. }
  48. /**
  49. * 最终登录用户
  50. * @param userInfo 包含账户名, 登录方式
  51. * @return
  52. */
  53. protected String loginAccount(UserInfo userInfo, BaseSystemInfo baseSystemInfo) throws LoginException {
  54. try{
  55. //获取用户实现类接口名称
  56. userInfo.setUserDetailKey(getUserDetailKey());
  57. //获取登录信息
  58. userInfo = getUserInfo(userInfo, baseSystemInfo);
  59. //预登陆
  60. preLogin(userInfo, baseSystemInfo);
  61. //登录
  62. login(userInfo, baseSystemInfo);
  63. }catch(Exception e){
  64. try {
  65. loginFailure(userInfo, baseSystemInfo, e);
  66. }catch (Exception e1){
  67. throw e1;
  68. }
  69. throw e;
  70. }
  71. loginSuccess(userInfo, baseSystemInfo);
  72. //返回token信息
  73. return userInfo.getToken();
  74. }
  75. /**
  76. * 切换多租户
  77. * @param userInfo
  78. * @return userAccount, tenantId, tenandDb
  79. * @throws LoginException
  80. */
  81. protected UserInfo switchTenant(UserInfo userInfo) throws LoginException {
  82. if (configValueUtil.isMultiTenancy()) {
  83. userInfo = loginService.getTenantAccount(userInfo);
  84. return userInfo;
  85. }
  86. userInfo.setTenantId(DEF_TENANT_ID);
  87. userInfo.setTenantDbConnectionString(DEF_TENANT_DB);
  88. userInfo.setTenantDbType(TenantVO.NONE);
  89. return userInfo;
  90. }
  91. /**
  92. * 获取系统配置
  93. * @param userInfo
  94. * @return
  95. */
  96. protected BaseSystemInfo getSysconfig(UserInfo userInfo) throws LoginException {
  97. BaseSystemInfo baseSystemInfo = loginService.getBaseSystemConfig(userInfo.getTenantId());
  98. if(baseSystemInfo != null && baseSystemInfo.getSingleLogin() != null){
  99. TenantProvider.setBaseSystemInfo(baseSystemInfo);
  100. }else{
  101. throw new TenantDatabaseException().setLogMsg(MsgCode.LOG110.get());
  102. }
  103. return baseSystemInfo;
  104. }
  105. /**
  106. * 获取登录设备
  107. * @return
  108. */
  109. protected DeviceType getDeviceType(){
  110. return UserProvider.getDeviceForAgent();
  111. }
  112. /**
  113. * 生成登录用户信息
  114. * @param userInfo
  115. * @return
  116. */
  117. protected UserInfo getUserInfo(UserInfo userInfo, BaseSystemInfo sysConfigInfo) throws LoginException {
  118. userInfo.setGrantType(getGrantType());
  119. userInfo = loginService.userInfo(userInfo, sysConfigInfo);
  120. return userInfo;
  121. }
  122. /**
  123. * 登录前执行
  124. * @param userInfo
  125. * @param baseSystemInfo
  126. */
  127. protected void preLogin(UserInfo userInfo, BaseSystemInfo baseSystemInfo) throws LoginException {
  128. }
  129. /**
  130. * 登录操作
  131. * @param userInfo
  132. * @param baseSystemInfo
  133. */
  134. protected void login(UserInfo userInfo, BaseSystemInfo baseSystemInfo) throws LoginException {
  135. UserProvider.login(userInfo, getLoginModel(userInfo, baseSystemInfo));
  136. }
  137. /**
  138. * 登录成功触发
  139. * @param userInfo
  140. * @param baseSystemInfo
  141. */
  142. protected void loginSuccess(UserInfo userInfo, BaseSystemInfo baseSystemInfo){
  143. }
  144. /**
  145. * 登录失败触发
  146. * @param baseSystemInfo
  147. */
  148. protected void loginFailure(UserInfo userInfo, BaseSystemInfo baseSystemInfo, Exception e){
  149. }
  150. protected abstract String getUserDetailKey();
  151. protected String createToken(UserInfo userInfo, BaseSystemInfo baseSystemInfo){
  152. //登录
  153. UserProvider.login(userInfo, getLoginModel(userInfo, baseSystemInfo));
  154. return StpUtil.getTokenValueNotCut();
  155. }
  156. /**
  157. * 更新轮询结果为成功
  158. */
  159. protected void updateTicketSuccess(UserInfo userInfo){
  160. String ticket = getJnpfTicket();
  161. if(!ticket.isEmpty()) {
  162. LoginTicketModel loginTicketModel = new LoginTicketModel()
  163. .setStatus(LoginTicketStatus.Success.getStatus())
  164. .setValue(StpUtil.getTokenValueNotCut())
  165. .setTheme(userInfo.getTheme());
  166. TicketUtil.updateTicket(ticket, loginTicketModel, null);
  167. }
  168. }
  169. /**
  170. * 更新轮询结果为失败
  171. */
  172. protected void updateTicketError(String msg){
  173. String ticket = getJnpfTicket();
  174. if(!ticket.isEmpty()) {
  175. LoginTicketModel loginTicketModel = new LoginTicketModel()
  176. .setStatus(LoginTicketStatus.ErrLogin.getStatus())
  177. .setValue(msg);
  178. TicketUtil.updateTicket(ticket, loginTicketModel, null);
  179. }
  180. }
  181. /**
  182. * 获取轮询ticket
  183. * @return
  184. */
  185. protected String getJnpfTicket(){
  186. return SaHolder.getRequest().getParam(AuthConsts.PARAMS_JNPF_TICKET, "");
  187. }
  188. protected boolean isValidJnpfTicket(){
  189. String jnpfTicket = getJnpfTicket();
  190. if(!jnpfTicket.isEmpty()){
  191. LoginTicketModel loginTicketModel = TicketUtil.parseTicket(jnpfTicket);
  192. if(loginTicketModel == null){
  193. return false;
  194. }
  195. }
  196. return true;
  197. }
  198. /**
  199. * 获取登录参数
  200. * @param userInfo
  201. * @param baseSystemInfo
  202. * @return
  203. */
  204. protected SaLoginParameter getLoginModel(UserInfo userInfo, BaseSystemInfo baseSystemInfo){
  205. SaLoginParameter loginModel = new SaLoginParameter();
  206. loginModel.setTimeout(userInfo.getTokenTimeout() * 60L);
  207. loginModel.setExtraData(getTokenExtraData(userInfo, baseSystemInfo));
  208. if(userInfo.getLoginDevice() == null) {
  209. loginModel.setDevice(getDeviceType().getDevice());
  210. userInfo.setLoginDevice(loginModel.getDeviceType());
  211. }else{
  212. loginModel.setDevice(userInfo.getLoginDevice());
  213. }
  214. return loginModel;
  215. }
  216. /**
  217. * 获取额外的JWT内容
  218. * @param userInfo
  219. * @param baseSystemInfo
  220. * @return
  221. */
  222. protected Map<String, Object> getTokenExtraData(UserInfo userInfo, BaseSystemInfo baseSystemInfo){
  223. Map<String, Object> tokenInfo = new HashMap<>();
  224. // tokenInfo.put("token", StpUtil.getTokenValue());
  225. tokenInfo.put("singleLogin", baseSystemInfo == null ? null : baseSystemInfo.getSingleLogin());
  226. tokenInfo.put("user_name", userInfo.getUserAccount());
  227. tokenInfo.put("user_id", userInfo.getUserId());
  228. tokenInfo.put("exp", userInfo.getOverdueTime().getTime());
  229. tokenInfo.put("token", userInfo.getId());
  230. return tokenInfo;
  231. }
  232. @Override
  233. public ActionResult<LogoutResultModel> logout() {
  234. UserProvider.logout();
  235. return ActionResult.success();
  236. }
  237. protected abstract String getGrantType();
  238. @Override
  239. public boolean requiresAuthentication() {
  240. String path = SaHolder.getRequest().getRequestPath();
  241. if(path != null && path.startsWith("/api/oauth")){
  242. path = path.replace("/api/oauth", "");
  243. }
  244. return pathMatcher.match(authenticationUrl, path);
  245. }
  246. }