电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術(shù)文章
文章詳情頁

Spring Boot 集成Shiro的多realm配置過程

瀏覽:116日期:2023-08-07 13:13:40

我在做畢設(shè)的時候采用shiro進行登錄認證和權(quán)限管理的實現(xiàn)。其中需求涉及使用三個角色分別是:學生、教師、管理員。現(xiàn)在要三者實現(xiàn)分開登錄。即需要三個Realm——StudentRealm和TeacherRealm、AdminRealm,分別處理學生、教師和管理員的驗證功能。

但是正常情況下,當定義了多個Realm,無論是學生登錄,教師登錄,還是管理員登錄,都會由這三個Realm共同處理。這是因為,當配置了多個Realm時,我們通常使用的認證器是shiro自帶的org.apache.shiro.authc.pam.ModularRealmAuthenticator,其中決定使用的Realm的是doAuthenticate()方法,源代碼如下:

protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { assertRealmsConfigured(); Collection<Realm> realms = getRealms(); if (realms.size() == 1) { return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken); } else { return doMultiRealmAuthentication(realms, authenticationToken); } }

上述代碼的意思就是如果有多個Realm就會使用所有配置的Realm。 只有一個的時候,就直接使用當前的Realm。

為了實現(xiàn)需求,我會創(chuàng)建一個org.apache.shiro.authc.pam.ModularRealmAuthenticator的子類,并重寫doAuthenticate()方法,讓特定的Realm完成特定的功能。如何區(qū)分呢?我會同時創(chuàng)建一個org.apache.shiro.authc.UsernamePasswordToken的子類,在其中添加一個字段loginType,用來標識登錄的類型,即是學生登錄、教師登錄,還是管理員登錄。具體步驟如下(我的代碼使用的是Groovy):

enum LoginType { STUDENT('Student'), ADMIN('Admin'), TEACHER('Teacher') private String type private LoginType(String type) { this.type = type } @Override public String toString() { return this.type.toString() }}

接下來新建org.apache.shiro.authc.UsernamePasswordToken的子類UserToken

import org.apache.shiro.authc.UsernamePasswordTokenclass UserToken extends UsernamePasswordToken { //登錄類型,判斷是學生登錄,教師登錄還是管理員登錄 private String loginType public UserToken(final String username, final String password,String loginType) { super(username,password) this.loginType = loginType } public String getLoginType() { return loginType } public void setLoginType(String loginType) { this.loginType = loginType }}

第三步:新建org.apache.shiro.authc.pam.ModularRealmAuthenticator的子類UserModularRealmAuthenticator:

import org.apache.shiro.authc.AuthenticationExceptionimport org.apache.shiro.authc.AuthenticationInfoimport org.apache.shiro.authc.AuthenticationTokenimport org.apache.shiro.authc.pam.ModularRealmAuthenticatorimport org.apache.shiro.realm.Realmimport org.slf4j.Loggerimport org.slf4j.LoggerFactory/** * 當配置了多個Realm時,我們通常使用的認證器是shiro自帶的org.apache.shiro.authc.pam.ModularRealmAuthenticator,其中決定使用的Realm的是doAuthenticate()方法 * * 自定義Authenticator * 注意,當需要分別定義處理學生和教師和管理員驗證的Realm時,對應(yīng)Realm的全類名應(yīng)該包含字符串“Student”“Teacher”,或者“Admin”。 * 并且,他們不能相互包含,例如,處理學生驗證的Realm的全類名中不應(yīng)該包含字符串'Admin'。 */class UserModularRealmAuthenticator extends ModularRealmAuthenticator { private static final Logger logger = LoggerFactory.getLogger(UserModularRealmAuthenticator.class) @Override protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException { logger.info('UserModularRealmAuthenticator:method doAuthenticate() execute ') // 判斷getRealms()是否返回為空 assertRealmsConfigured() // 強制轉(zhuǎn)換回自定義的CustomizedToken UserToken userToken = (UserToken) authenticationToken // 登錄類型 String loginType = userToken?.getLoginType() // 所有Realm Collection<Realm> realms = getRealms() // 登錄類型對應(yīng)的所有Realm Collection<Realm> typeRealms = new ArrayList<>() for (Realm realm : realms) { if (realm?.getName()?.contains(loginType)) typeRealms?.add(realm) } // 判斷是單Realm還是多Realm if (typeRealms?.size() == 1){ logger.info('doSingleRealmAuthentication() execute ') return doSingleRealmAuthentication(typeRealms?.get(0), userToken) } else{ logger.info('doMultiRealmAuthentication() execute ') return doMultiRealmAuthentication(typeRealms, userToken) } }}

第四步:創(chuàng)建分別處理學生登錄和教師登錄、管理員登錄的Realm: 我這里直接貼出了我項目中的代碼,你們可以根據(jù)具體的需求進行操作。 AdminShiroRealm :

package com.ciyou.edu.config.shiro.adminimport com.ciyou.edu.config.shiro.common.UserTokenimport com.ciyou.edu.entity.Adminimport com.ciyou.edu.service.AdminServiceimport com.ciyou.edu.service.PermissionServiceimport org.apache.shiro.authc.AuthenticationExceptionimport org.apache.shiro.authc.AuthenticationInfoimport org.apache.shiro.authc.AuthenticationTokenimport org.apache.shiro.authc.SimpleAuthenticationInfoimport org.apache.shiro.authc.UnknownAccountExceptionimport org.apache.shiro.authz.AuthorizationExceptionimport org.apache.shiro.authz.AuthorizationInfoimport org.apache.shiro.authz.SimpleAuthorizationInfoimport org.apache.shiro.realm.AuthorizingRealmimport org.apache.shiro.subject.PrincipalCollectionimport org.apache.shiro.util.ByteSourceimport org.slf4j.Loggerimport org.slf4j.LoggerFactoryimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.context.annotation.Lazyclass AdminShiroRealm extends AuthorizingRealm { private static final Logger logger = LoggerFactory.getLogger(AdminShiroRealm.class) @Autowired @Lazy private AdminService adminService @Autowired @Lazy private PermissionService permissionService @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { logger.info('開始Admin身份認證...') UserToken userToken = (UserToken)token String adminName = userToken?.getUsername() //獲取用戶名,默認和login.html中的adminName對應(yīng)。 Admin admin = adminService?.findByAdminName(adminName) if (admin == null) { //沒有返回登錄用戶名對應(yīng)的SimpleAuthenticationInfo對象時,就會在LoginController中拋出UnknownAccountException異常 throw new UnknownAccountException('用戶不存在!') } //驗證通過返回一個封裝了用戶信息的AuthenticationInfo實例即可。 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( admin, //用戶信息 admin?.getPassword(), //密碼 getName() //realm name ) authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(admin?.getAdminName())) //設(shè)置鹽 logger.info('返回Admin認證信息:' + authenticationInfo) return authenticationInfo }//當訪問到頁面的時候,鏈接配置了相應(yīng)的權(quán)限或者shiro標簽才會執(zhí)行此方法否則不會執(zhí)行 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { logger.info('開始Admin權(quán)限授權(quán)(進行權(quán)限驗證!!)') if (principals == null) { throw new AuthorizationException('PrincipalCollection method argument cannot be null.') } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo() if(principals?.getPrimaryPrincipal() instanceof Admin){ Admin admin = (Admin) principals?.getPrimaryPrincipal() logger.info('當前Admin :' + admin ) authorizationInfo?.addRole('Admin') //每次都從數(shù)據(jù)庫重新查找,確保能及時更新權(quán)限 admin?.setPermissionList(permissionService?.findPermissionByAdmin(admin?.getAdminId())) admin?.getPermissionList()?.each {current_Permission -> authorizationInfo?.addStringPermission(current_Permission?.getPermission()) } logger.info('當前Admin授權(quán)角色:' +authorizationInfo?.getRoles() + ',權(quán)限:' + authorizationInfo?.getStringPermissions()) return authorizationInfo } }}

TeacherShiroRealm :

package com.ciyou.edu.config.shiro.teacherimport com.ciyou.edu.config.shiro.common.UserTokenimport com.ciyou.edu.entity.Teacherimport com.ciyou.edu.service.TeacherServiceimport org.apache.shiro.authc.*import org.apache.shiro.authz.AuthorizationExceptionimport org.apache.shiro.authz.AuthorizationInfoimport org.apache.shiro.authz.SimpleAuthorizationInfoimport org.apache.shiro.realm.AuthorizingRealmimport org.apache.shiro.subject.PrincipalCollectionimport org.apache.shiro.util.ByteSourceimport org.slf4j.Loggerimport org.slf4j.LoggerFactoryimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.context.annotation.Lazyclass TeacherShiroRealm extends AuthorizingRealm { private static final Logger logger = LoggerFactory.getLogger(TeacherShiroRealm.class) //在自定義Realm中注入的Service聲明中加入@Lazy注解即可解決@cacheble注解無效問題 //解決同時使用Redis緩存數(shù)據(jù)和緩存shiro時,@cacheble無效的問題 @Autowired @Lazy private TeacherService teacherService @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { logger.info('開始Teacher身份認證..') UserToken userToken = (UserToken)token String teacherId = userToken?.getUsername() Teacher teacher = teacherService?.findByTeacherId(teacherId) if (teacher == null) { //沒有返回登錄用戶名對應(yīng)的SimpleAuthenticationInfo對象時,就會在LoginController中拋出UnknownAccountException異常 throw new UnknownAccountException('用戶不存在!') } //驗證通過返回一個封裝了用戶信息的AuthenticationInfo實例即可。 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( teacher, //用戶信息 teacher?.getPassword(), //密碼 getName() //realm name ) authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(teacher?.getTeacherId())) //設(shè)置鹽 return authenticationInfo }//當訪問到頁面的時候,鏈接配置了相應(yīng)的權(quán)限或者shiro標簽才會執(zhí)行此方法否則不會執(zhí)行 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { logger.info('開始Teacher權(quán)限授權(quán)') if (principals == null) { throw new AuthorizationException('PrincipalCollection method argument cannot be null.') } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo() if(principals?.getPrimaryPrincipal() instanceof Teacher){ authorizationInfo?.addRole('Teacher') return authorizationInfo } }}

StudentShiroRealm :

package com.ciyou.edu.config.shiro.studentimport com.ciyou.edu.config.shiro.common.UserTokenimport com.ciyou.edu.entity.Studentimport com.ciyou.edu.service.StudentServiceimport org.apache.shiro.authc.*import org.apache.shiro.authz.AuthorizationExceptionimport org.apache.shiro.authz.AuthorizationInfoimport org.apache.shiro.authz.SimpleAuthorizationInfoimport org.apache.shiro.realm.AuthorizingRealmimport org.apache.shiro.subject.PrincipalCollectionimport org.apache.shiro.util.ByteSourceimport org.slf4j.Loggerimport org.slf4j.LoggerFactoryimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.context.annotation.Lazyclass StudentShiroRealm extends AuthorizingRealm { private static final Logger logger = LoggerFactory.getLogger(StudentShiroRealm.class) //在自定義Realm中注入的Service聲明中加入@Lazy注解即可解決@cacheble注解無效問題 //解決同時使用Redis緩存數(shù)據(jù)和緩存shiro時,@cacheble無效的問題 @Autowired @Lazy private StudentService studentService @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { logger.info('開始Student身份認證..') UserToken userToken = (UserToken)token String studentId = userToken?.getUsername() Student student = studentService?.findByStudentId(studentId) if (student == null) { //沒有返回登錄用戶名對應(yīng)的SimpleAuthenticationInfo對象時,就會在LoginController中拋出UnknownAccountException異常 throw new UnknownAccountException('用戶不存在!') } //驗證通過返回一個封裝了用戶信息的AuthenticationInfo實例即可。 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( student, //用戶信息 student?.getPassword(), //密碼 getName() //realm name ) authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(student?.getStudentId())) //設(shè)置鹽 return authenticationInfo }//當訪問到頁面的時候,鏈接配置了相應(yīng)的權(quán)限或者shiro標簽才會執(zhí)行此方法否則不會執(zhí)行 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { logger.info('開始Student權(quán)限授權(quán)') if (principals == null) { throw new AuthorizationException('PrincipalCollection method argument cannot be null.') } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo() if(principals?.getPrimaryPrincipal() instanceof Student){ authorizationInfo?.addRole('Student') return authorizationInfo } }}

接下來是對Shiro進行多realm的注解配置。 這里直接貼出我項目中的代碼。

Spring Boot 集成Shiro的多realm配置過程

上面是我進行shiro進行配置的類,下面是主要的一些代碼:

//SecurityManager 是 Shiro 架構(gòu)的核心,通過它來鏈接Realm和用戶(文檔中稱之為Subject.) @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager() //設(shè)置realm. securityManager.setAuthenticator(modularRealmAuthenticator()) List<Realm> realms = new ArrayList<>() //添加多個Realm realms.add(adminShiroRealm()) realms.add(teacherShiroRealm()) realms.add(studentShiroRealm()) securityManager.setRealms(realms) // 自定義緩存實現(xiàn) 使用redis securityManager.setCacheManager(cacheManager()) // 自定義session管理 使用redis securityManager.setSessionManager(sessionManager()) //注入記住我管理器; securityManager.setRememberMeManager(rememberMeManager()) return securityManager } /** * 系統(tǒng)自帶的Realm管理,主要針對多realm * */ @Bean public ModularRealmAuthenticator modularRealmAuthenticator(){ //自己重寫的ModularRealmAuthenticator UserModularRealmAuthenticator modularRealmAuthenticator = new UserModularRealmAuthenticator() modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy()) return modularRealmAuthenticator } @Bean public AdminShiroRealm adminShiroRealm() { AdminShiroRealm adminShiroRealm = new AdminShiroRealm() adminShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher())//設(shè)置解密規(guī)則 return adminShiroRealm } @Bean public StudentShiroRealm studentShiroRealm() { StudentShiroRealm studentShiroRealm = new StudentShiroRealm() studentShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher())//設(shè)置解密規(guī)則 return studentShiroRealm } @Bean public TeacherShiroRealm teacherShiroRealm() { TeacherShiroRealm teacherShiroRealm = new TeacherShiroRealm() teacherShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher())//設(shè)置解密規(guī)則 return teacherShiroRealm } //因為我們的密碼是加過密的,所以,如果要Shiro驗證用戶身份的話,需要告訴它我們用的是md5加密的,并且是加密了兩次。同時我們在自己的Realm中也通過SimpleAuthenticationInfo返回了加密時使用的鹽。這樣Shiro就能順利的解密密碼并驗證用戶名和密碼是否正確了。 @Bean public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher() hashedCredentialsMatcher.setHashAlgorithmName('md5')//散列算法:這里使用MD5算法; hashedCredentialsMatcher.setHashIterations(2)//散列的次數(shù),比如散列兩次,相當于 md5(md5('')); return hashedCredentialsMatcher; }

接下來就是Controller中實現(xiàn)登錄的功能了,這里我只貼出我項目中Admin登錄的代碼:

package com.ciyou.edu.controller.adminimport com.ciyou.edu.config.shiro.common.LoginTypeimport com.ciyou.edu.config.shiro.common.UserTokenimport com.ciyou.edu.entity.Adminimport com.ciyou.edu.utils.JSONUtilimport org.apache.shiro.SecurityUtilsimport org.apache.shiro.authc.AuthenticationExceptionimport org.apache.shiro.subject.Subjectimport org.slf4j.Loggerimport org.slf4j.LoggerFactoryimport org.springframework.stereotype.Controllerimport org.springframework.web.bind.annotation.RequestMappingimport org.springframework.web.bind.annotation.RequestMethodimport org.springframework.web.bind.annotation.ResponseBody/** * @Author C. * @Date 2018-02-02 20:46 * admin登錄Controller */@Controllerclass AdminLoginController { private static final Logger logger = LoggerFactory.getLogger(AdminLoginController.class) private static final String ADMIN_LOGIN_TYPE = LoginType.ADMIN.toString() /** * admin登錄 * @param admin * @return 登錄結(jié)果 */ @RequestMapping(value='/adminLogin',method=RequestMethod.POST, produces='application/json;charset=UTF-8') @ResponseBody public String loginAdmin(Admin admin){ logger.info('登錄Admin: ' + admin) //后臺校驗提交的用戶名和密碼 if(!admin?.getAdminName() || admin?.adminName?.trim() == ''){ return JSONUtil.returnFailReuslt('賬號不能為空') }else if(!admin?.getPassword() || admin?.getPassword()?.trim() == ''){ return JSONUtil.returnFailReuslt('密碼不能為空') }else if(admin?.getAdminName()?.length() < 3 || admin?.getAdminName()?.length() >15){ return JSONUtil.returnFailReuslt('賬號長度必須在3~15之間') }else if(admin?.getPassword()?.length() < 3 || admin?.getPassword()?.length() >15){ return JSONUtil.returnFailReuslt('密碼長度必須在3~15之間') } //獲取Subject實例對象 //在shiro里面所有的用戶的會話信息都會由Shiro來進行控制,那么也就是說只要是與用戶有關(guān)的一切的處理信息操作都可以通過Shiro取得, // 實際上可以取得的信息可以有用戶名、主機名稱等等,這所有的信息都可以通過Subject接口取得 Subject subject = SecurityUtils.getSubject() //將用戶名和密碼封裝到繼承了UsernamePasswordToken的userToken UserToken userToken = new UserToken(admin?.getAdminName(), admin?.getPassword(), ADMIN_LOGIN_TYPE) userToken.setRememberMe(false) try { //認證 // 傳到ModularRealmAuthenticator類中,然后根據(jù)ADMIN_LOGIN_TYPE傳到AdminShiroRealm的方法進行認證 subject?.login(userToken) //Admin存入session SecurityUtils.getSubject()?.getSession()?.setAttribute('admin',(Admin)subject?.getPrincipal()) return JSONUtil.returnSuccessResult('登錄成功') } catch (AuthenticationException e) { //認證失敗就會拋出AuthenticationException這個異常,就對異常進行相應(yīng)的操作,這里的處理是拋出一個自定義異常ResultException //到時候我們拋出自定義異常ResultException,用戶名或者密碼錯誤 logger.info('認證錯誤:' + e.getMessage()) return JSONUtil.returnFailReuslt('賬號或者密碼錯誤') } } @RequestMapping(value='/admin/adminLogout') public String logoutAdmin(){ SecurityUtils.getSubject()?.logout() return 'redirect:/adminLogin' }}

現(xiàn)在Spring Boot中集成Shiro實現(xiàn)多realm配置就完成了。

感謝以下博文,在我學習的過程中給了我很多幫助,我的博文也有一些內(nèi)容參考他們的,還不夠清楚的讀者可以參考: shiro實現(xiàn)不同身份使用不同Realm進行驗證 SpringBoot+Shiro學習之數(shù)據(jù)庫動態(tài)權(quán)限管理和Redis緩存 Springboot多realm集成,無ini文件,無xml配置

想看項目具體源碼,或者對我項目感興趣的可以查看:CIYOU

到此這篇關(guān)于Spring Boot 集成Shiro的多realm配置過程的文章就介紹到這了,更多相關(guān)Spring Boot多realm配置內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 十字轴_十字轴万向节_十字轴总成-南京万传机械有限公司 | 铁素体测量仪/检测仪/铁素体含量测试仪-苏州圣光仪器有限公司 | 宜兴紫砂壶知识分享 - 宜兴壶人 医用空气消毒机-医用管路消毒机-工作服消毒柜-成都三康王 | 广州监控安装公司_远程监控_安防弱电工程_无线wifi覆盖_泉威安防科技 | 细石混凝土泵_厂家_价格-烟台九达机械有限公司| 江苏皓越真空设备有限公司| 洁净棚-洁净工作棚-无菌室-净化工程公司_北京卫护科技有限公司 | 东莞办公家具厂家直销-美鑫【免费3D效果图】全国办公桌/会议桌定制 | CXB船用变压器-JCZ系列制动器-HH101船用铜质开关-上海永上船舶电器厂 | 超声骨密度仪,双能X射线骨密度仪【起草单位】,骨密度检测仪厂家 - 品源医疗(江苏)有限公司 | lcd条形屏-液晶长条屏-户外广告屏-条形智能显示屏-深圳市条形智能电子有限公司 | 消泡剂-水处理消泡剂-涂料消泡剂-切削液消泡剂价格-东莞德丰消泡剂厂家 | 北京征地律师,征地拆迁律师,专业拆迁律师,北京拆迁律师,征地纠纷律师,征地诉讼律师,征地拆迁补偿,拆迁律师 - 北京凯诺律师事务所 | vr安全体验馆|交通安全|工地安全|禁毒|消防|安全教育体验馆|安全体验教室-贝森德(深圳)科技 | 污泥烘干机-低温干化机-工业污泥烘干设备厂家-焦作市真节能环保设备科技有限公司 | 米顿罗计量泵(科普)——韬铭机械 | 自动记录数据电子台秤,记忆储存重量电子桌称,设定时间记录电子秤-昆山巨天 | 大巴租车平台承接包车,通勤班车,巴士租赁业务 - 鸿鸣巴士 | 大立教育官网-一级建造师培训-二级建造师培训-造价工程师-安全工程师-监理工程师考试培训 | 广东燎了网络科技有限公司官网-网站建设-珠海网络推广-高端营销型外贸网站建设-珠海专业h5建站公司「了了网」 | 章丘丰源机械有限公司 - 三叶罗茨风机,罗茨鼓风机,罗茨风机 | 岩棉板|岩棉复合板|聚氨酯夹芯板|岩棉夹芯板|彩钢夹芯板-江苏恒海钢结构 | 撕碎机,撕破机,双轴破碎机-大件垃圾破碎机厂家 | 茶楼装修设计_茶馆室内设计效果图_云臻轩茶楼装饰公司 | 浙江华锤电器有限公司_地磅称重设备_防作弊地磅_浙江地磅售后维修_无人值守扫码过磅系统_浙江源头地磅厂家_浙江工厂直营地磅 | 高中学习网-高考生信息学习必备平台 | 脉冲布袋除尘器_除尘布袋-泊头市净化除尘设备生产厂家 | 【德信自动化】点胶机_全自动点胶机_自动点胶机厂家_塑料热压机_自动螺丝机-深圳市德信自动化设备有限公司 | 注浆压力变送器-高温熔体传感器-矿用压力传感器|ZHYQ朝辉 | 硅PU球场、篮球场地面施工「水性、环保、弹性」硅PU材料生产厂家-广东中星体育公司 | 黄石妇科医院_黄石东方女子医院_黄石东方妇产医院怎么样 | 杜康白酒加盟_杜康酒代理_杜康酒招商加盟官网_杜康酒厂加盟总代理—杜康酒神全国运营中心 | 冷油器-冷油器换管改造-连云港灵动列管式冷油器生产厂家 | 上海诺狮景观规划设计有限公司 | 沙盘模型公司_沙盘模型制作公司_建筑模型公司_工业机械模型制作厂家 | 地磅-电子地磅维修-电子吊秤-汽车衡-无人值守系统-公路治超-鹰牌衡器 | 自动气象站_气象站监测设备_全自动气象站设备_雨量监测站-山东风途物联网 | CTAB,表面活性剂1631溴型(十六烷基三甲基溴化铵)-上海升纬化工原料有限公司 | 北京易通慧公司从事北京网站优化,北京网络推广、网站建设一站式服务商-北京网站优化公司 | 楼承板-开口楼承板-闭口楼承板-无锡海逵| 天津市能谱科技有限公司-专业的红外光谱仪_红外测油仪_紫外测油仪_红外制样附件_傅里叶红外光谱技术生产服务厂商 |