为什么要用shiro ???

如题,为什么要用shiro.


首先本人是新学者,并没有贬低shiro的意思。

shiro两大功能,1.验证是不是某个角色,也可以说是验证登录

2.验证该角色有没有某种权限。


如果不用这个框架,本人思路就是写验证的dao,角色权限等信息都在数据库里。

直接调用dao就可以验证。
使用shiro,同样要写验证的dao,验证时使用shiro,再由shiro调用dao。
这不是多了一步吗?


shiro框架到底简化了什么。

2个回答

你现在有辆车,而且你还有驾照。 你非要走,时间不是成本吗?

个人理解:安全,可以帮你实现加密,更好管理,也容易增加功能,同时也有缓存管理;其实说到底就是个框架,工程量大,用shiro肯定轻松,如果只是实现简单的登陆注册功能,那不用也无妨。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
Python+OpenCV计算机视觉

Python+OpenCV计算机视觉

对shiro框架的一些疑惑

shriro框架的锁定,是存储在缓存里的么?那为什么还在数据库里记录是否锁定?如果服务器重启,锁定是不是解除?那框架对shiro存储在数据库里是否锁定的标记怎么处理?就是说,如果我被锁定了十分钟,一旦服务器重启,这十分钟怎么弄?相应的rememberme的处理是怎样的?。。最后一个问题,密码匹配是将匹配密码再加密一遍与数据库加过密的密码匹配,还是只需要登入密码就可以

shiro+redis缓存插件的作用是什么

看到别人的项目里有这个插件,这个插件要怎么使用,有没有API文档什么的可以看

如何在javaweb项目中使用shiro

如何在javaweb项目中使用shiro。。。。。。。。。。。

请问shiro和springsecurity的区别是什么

请问shiro和springsecurity的区别是什么,两个同为权限框架,有什么区别?

shiro JSP使用标签报错

在JSP页面使用shiro标签报错,要怎么改?求大神指点 java.lang.IllegalArgumentException: Wildcard string cannot be null or empty. Make sure permission strings are properly formatted. org.apache.shiro.authz.permission.WildcardPermission.setParts(WildcardPermission.java:151) org.apache.shiro.authz.permission.WildcardPermission.<init>(WildcardPermission.java:142) org.apache.shiro.authz.permission.WildcardPermission.<init>(WildcardPermission.java:138) org.apache.shiro.authz.permission.WildcardPermissionResolver.resolvePermission(WildcardPermissionResolver.java:41) org.apache.shiro.realm.AuthorizingRealm.resolvePermissions(AuthorizingRealm.java:433) org.apache.shiro.realm.AuthorizingRealm.getPermissions(AuthorizingRealm.java:409) org.apache.shiro.realm.AuthorizingRealm.isPermitted(AuthorizingRealm.java:466) org.apache.shiro.realm.AuthorizingRealm.isPermitted(AuthorizingRealm.java:462) org.apache.shiro.realm.AuthorizingRealm.isPermitted(AuthorizingRealm.java:457) org.apache.shiro.authz.ModularRealmAuthorizer.isPermitted(ModularRealmAuthorizer.java:223) org.apache.shiro.mgt.AuthorizingSecurityManager.isPermitted(AuthorizingSecurityManager.java:113) org.apache.shiro.subject.support.DelegatingSubject.isPermitted(DelegatingSubject.java:158) org.apache.shiro.web.tags.PermissionTag.isPermitted(PermissionTag.java:66) org.apache.shiro.web.tags.HasPermissionTag.showTagBody(HasPermissionTag.java:32) org.apache.shiro.web.tags.PermissionTag.onDoStartTag(PermissionTag.java:57) org.apache.shiro.web.tags.SecureTag.doStartTag(SecureTag.java:53) org.apache.jsp.success_jsp._jspx_meth_shiro_005fhasPermission_005f0(success_jsp.java:205) org.apache.jsp.success_jsp._jspService(success_jsp.java:122) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) index.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <body> <h2>Hello World!</h2> <form action="/login.do" method="post"> <table> <tr> <td>账号:</td> <td><input name="username" value="${users.username}"/></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password" value="${users.password}"/></td><br/> <td><input type="submit" value="login"/><span style="font-size: 12px;color: red">${error}</span></td> </tr> </table> </form> </body> </html> 登录成功之后的页面success.jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> ${info }欢迎你<br/> <shiro:hasRole name="admin"> 欢迎有admin角色的用户!<shiro:principal/> </shiro:hasRole> <shiro:hasPermission name="student:create"> 欢迎有student:create权限的用户!<shiro:principal/> </shiro:hasPermission> </body> </html> controller @Controller public class UsersController { @Autowired private UsersService usersService; @RequestMapping("/login") public String login(Model model,Users users){ Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(users.getUsername(),users.getPassword()); try { subject.login(token); // Model model1 = (Model) subject.getSession(); // model1.addAttribute("info","welcome to"); // Session session = subject.getSession(); // session.setAttribute("info","Welcome To Shiro"); return "redirect:/success.jsp"; }catch (Exception e) { e.printStackTrace(); model.addAttribute("users",users); model.addAttribute("error","用户名或密码错误"); return "index"; } } }

自己写filter来控制权限好还是用shiro之类的框架

自己写、shiro、spring Security各自的优缺点

请问 使用shiro想去掉remmemberMe

shiro 并没有配置 rememberMe相关配置 , 但是在浏览器cookie里却有 rememberMe ,造成session过期,一刷新浏览器又能继续访问需要认证的链接, 求大神指导. 小弟在此谢过了. ![图片说明](https://img-ask.csdn.net/upload/201710/15/1508048156_930368.png) ![图片说明](https://img-ask.csdn.net/upload/201710/15/1508048186_891445.png) <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd "> <!-- 凭证匹配器 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="HashAlgorithmName" value="md5"></property> <property name="hashIterations" value="1"></property> </bean> <!-- realm --> <bean id="userRealm" class="cn.itcast.act_web.shiro.dao.UserRealm"> <property name="credentialsMatcher" ref="credentialsMatcher" ></property> </bean> <!-- ehcache缓存管理器--> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"></property> </bean> <!-- Shiro 的 session管理器 <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="globalSessionTimeout" value="180000"></property> <property name="deleteInvalidSessions" value="true"></property> </bean> --> <!-- securityManager --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm"></property> <!-- <property name="cacheManager" ref="cacheManager"></property> --> <!-- <property name="sessionManager" ref="sessionManager"></property> --> </bean> <!-- web.xml 中shiro的filter 对应的bean --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"></property> <property name="loginUrl" value="/loginUI.jsp"></property> <!-- <property name="successUrl" value="/home/index.action"></property> --> <property name="unauthorizedUrl" value="/loginUI.jsp"></property> <property name="filterChainDefinitions" > <value> <!-- 静态资源匿名访问 --> /images/** = anon /js/** = anon /styles/** = anon /image/** = anon /script/** = anon /style/** = anon <!-- 必须将登录action 及登录提交action匿名 --> /home/index.action*= anon /loginsubmit.action* = anon <!-- /validatecode.jsp* = anon --> <!-- 退出登陆的地址,shiro去清楚session --> /home/logout.action = logout <!-- /cgd/addcgd.action = perms["cgd/addcgd.act"] --> <!-- 如果设置 Cookie 记住我, 则不能使用此user过滤器,还会拦截 --> /index.jsp* = user <!-- /first.action* = user --> <!-- /welcome.action* = user --> <!-- /getmenus.action* = user --> <!-- 所有的URL都必须认证通过才能访问, --> /** = authc <!-- 所有的url 都可以匿名访问 --> <!-- /** = anon --> </value> </property> </bean> </beans>

shiro session使用redis存储

场景:使用redis存储shiro的session 当根据sessionId从redis中获取session对象时应返回null ``` try { if (null != sessionId) { byte[] bytes = robertRedisClient.get(redisSerializer.serialize(SHIRO_SESSION + sessionId.toString())); if (1 > bytes.length) { return null; } return (Session) redisSerializer.deserialize(bytes); } return null; } catch (Exception e) { log.error("获取shiro的session时发生异常,异常详细信息:\n {}", ExceptionUtils.getStackTrace(e)); return null; } ``` 问题:1、后台日志上可以看到nullpointexception,可也有新session创建的日志输出 ``` 2019-05-06 16:41:46.583 [XNIO-1 task-6] ERROR- com.robert.auth.session.RedisSessionDao - 获取shiro的session时发生异常,异常详细信息: java.lang.NullPointerException at com.robert.auth.session.RedisSessionDao.doReadSession(RedisSessionDao.java:54) at org.apache.shiro.session.mgt.eis.AbstractSessionDAO.readSession(AbstractSessionDAO.java:168) 2019-05-06 16:41:46.583 [XNIO-1 task-6] DEBUG- com.robert.auth.session.RedisSessionDao - 新增一个session:3dfe4f26-ddb2-4b1e-9fc0-fa772cd60dd8 2019-05-06 16:41:46.583 [XNIO-1 task-6] DEBUG- com.robert.auth.session.RedisSessionDao - 创建session的host:192.168.0.221,session主键:3dfe4f26-ddb2-4b1e-9fc0-fa772cd60dd8,最后访问时间:Mon May 06 16:41:46 CST 2019 2019-05-06 16:41:46.584 [XNIO-1 task-6] DEBUG- com.robert.auth.redis.RobertRedisClient - 向redis中写数据:key-shiro-session:3dfe4f26-ddb2-4b1e-9fc0-fa772cd60dd8,value-...,timeout-1800 2019-05-06 16:41:46.585 [XNIO-1 task-6] DEBUG- com.robert.auth.session.RedisSessionDao - 更新shiro session :3dfe4f26-ddb2-4b1e-9fc0-fa772cd60dd8 2019-05-06 16:41:46.585 [XNIO-1 task-6] DEBUG- com.robert.auth.session.RedisSessionDao - 创建session的host:192.168.0.221,session主键:3dfe4f26-ddb2-4b1e-9fc0-fa772cd60dd8,最后访问时间:Mon May 06 16:41:46 CST 2019 2019-05-06 16:41:46.585 [XNIO-1 task-6] DEBUG- com.robert.auth.redis.RobertRedisClient - 向redis中写数据:key-shiro-session:3dfe4f26-ddb2-4b1e-9fc0-fa772cd60dd8,value-...,timeout-1800 ``` 2、客户端获取不到请求响应

Shiro缓存问题,Spring整合Shiro

Spring+Mybatis+Shiro整合时,shiro第一次验证身份通过后,后续验证都不生效,必须清除浏览器缓存才可生效,请问这是为什么呢?

shiro拦截器使用的问题(springboot+shiro)

使用shiro开发的时候,配置拦截器有什么作用吗?配置了拦截器之后因该怎么写才能处理拦截到的请求呢? 初始化的时候配置了拦截器。但是是跳到了controller之后调用的Subject.login()方法进入的用户身份验证的方法不是吗? 那拦截器还有啥用?如何配置拦截器,可以让制定的链接直接进入用户身份验证的方法? springboot+shiro

shiro单个实例权限是什么意思

![图片说明](https://img-ask.csdn.net/upload/201705/02/1493703358_661224.png)

idea启动shiro管理的项目

eclipse换成idea启动项目,一直报这个错。 找了一天的问题,网上说的各种办法都试了,一直报这个错。 type Exception report message java.lang.ClassNotFoundException: org.apache.jsp.index_html description The server encountered an internal error that prevented it from fulfilling this request. exception org.apache.jasper.JasperException: java.lang.ClassNotFoundException: org.apache.js.index_html org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:176) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347) org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263) root cause java.lang.ClassNotFoundException: org.apache.jsp.index_html java.net.URLClassLoader.findClass(URLClassLoader.java:381) org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:131) org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:62) org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:171) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) javax.servlet.http.HttpServlet.service(HttpServlet.java:729) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347) org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263) note The full stack trace of the root cause is available in the Apache Tomcat/8.0.33 logs.

不知道为什么,我shiro生产的是这个而不是UUID?

![图片说明](https://img-ask.csdn.net/upload/202006/10/1591760763_114345.png) 不知道为什么,我shiro生产的是这个而不是UUID? ``` /** * Session ID 生成器 * * @return JavaUuidSessionIdGenerator */ @Bean public JavaUuidSessionIdGenerator sessionIdGenerator() { return new JavaUuidSessionIdGenerator(); } ``` ``` /** * {@link SessionIdGenerator} that generates String values of JDK {@link java.util.UUID}'s as the session IDs. * * @since 1.0 */ public class JavaUuidSessionIdGenerator implements SessionIdGenerator { /** * Ignores the method argument and simply returns * {@code UUID}.{@link java.util.UUID#randomUUID() randomUUID()}.{@code toString()}. * * @param session the {@link Session} instance to which the ID will be applied. * @return the String value of the JDK's next {@link UUID#randomUUID() randomUUID()}. */ public Serializable generateId(Session session) { return UUID.randomUUID().toString(); } } ```

web.xml中shiro过滤器和Struts2过滤器配置的是不是存在先后顺序问题

今天在练习一个项目时,用到了shiro框架,刚开始在web.xml中把shiro过滤器的声明放到了struts2过滤器的后面,然后在spring配置文件中注入shiro的URL拦截规则,运行时发现并没有按照预想的规则进行拦截。经过一段时间调试后,发现书上web.xml的配置是把shiro的过滤器声明放到了最前面,然后我也试着把shiro的声明放到了struts过滤器声明的前面,最后成功进行了拦截。想问一下web.xml中shiro过滤器和Struts2过滤器配置的是不是存在先后顺序问题?希望知道原理的大佬能解答一下。 spring配置文件中用到的shiro拦截规则如下: ``` <!-- 配置一个bean用于创建shiro框架用的过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 注入安全管理器 --> <property name="securityManager" ref="securityManager"></property> <!-- 注入当前系统登录页面 --> <property name="loginUrl" value="/login.jsp"></property> <!-- 注入登录成功页面 --> <property name="successUrl" value="/index.jsp"></property> <!-- 注入权限不足页面 --> <property name="unauthorizedUrl" value="/unauthorizedUrl.jsp"></property> <!-- 注入URL拦截规则 --> <property name="filterChainDefinitions"> <value> /login.jsp* = anon /userAction_login.action = anon /* = authc </value> </property> </bean> ``` 在页面点击登录后,会跳到index.jsp,由于在index.jsp中我用了重定向,书上说会被最后一个拦截规则拦截,需要认证通过才能访问,所以要会跳转到登录页面。而开始我在web.xml文件中吧shiro的过滤器声明放到了最后面,发现并没有被拦截,直接访问到了主页。而把shiro的声明放到struts过滤器声明的前面时,却能被正确拦截。有点不太明白。。想请教一下。

为什么shiro使用session过期时间在chrome浏览器设置无效,timeout一直是-1000,火狐浏览器则可以设置

**为什么shiro使用session过期时间在chrome浏览器设置无效,timeout一直是-1000,火狐浏览器则可以设置** ``` <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- 调用我们配置的权限管理器 --> <property name="securityManager" ref="securityManager" /> <!-- 配置我们的登录请求地址 --> <property name="loginUrl" value="/login" /> <!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 --> <property name="unauthorizedUrl" value="/unauthorized" /> <!-- 退出 --> <property name="filters"> <util:map> <entry key="logout" value-ref="logoutFilter" /> </util:map> </property> <!-- 权限配置 --> <property name="filterChainDefinitions"> <value> <!-- anon表示此地址不需要任何权限即可访问 --> /login=anon /index=anon /static/**=anon <!-- 只对业务功能进行权限管理,权限配置本身不需要没有做权限要求,这样做是为了不让初学者混淆 --> /config/**=anon /doLogout=logout <!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login --> /** = authc </value> </property> </bean> <!-- 退出过滤器 --> <bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter"> <property name="redirectUrl" value="/index" /> </bean> <!-- 会话ID生成器 --> <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" /> <!-- 会话Cookie模板 关闭浏览器立即失效 --> <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="sid" /> <property name="httpOnly" value="true" /> <property name="maxAge" value="-1" /> </bean> <!-- 会话DAO --> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"> <property name="sessionIdGenerator" ref="sessionIdGenerator" /> </bean> <!-- 会话验证调度器,每30分钟执行一次验证 ,设定会话超时及保存 --> <bean name="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler"> <property name="interval" value="1800000" /> <property name="sessionManager" ref="sessionManager" /> </bean> <!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- 全局会话超时时间(单位毫秒),默认30分钟 --> <property name="globalSessionTimeout" value="1800000" /> <property name="deleteInvalidSessions" value="true" /> <property name="sessionValidationSchedulerEnabled" value="true" /> <property name="sessionValidationScheduler" ref="sessionValidationScheduler" /> <property name="sessionDAO" ref="sessionDAO" /> <property name="sessionIdCookieEnabled" value="true" /> <property name="sessionIdCookie" ref="sessionIdCookie" /> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="databaseRealm" /> <property name="sessionManager" ref="sessionManager" /> </bean> ``` globalSessionTimeout设置为10000(10秒过期)在chrome无效,在火狐就可以,进入AbstractValidatingSessionManager源码中查看,获取到的invalidCount一直是0,并且timeout一直是-1000,所以session一直不会过期,不知道怎么解决

关于shiro认证登陆这块

最近在研究Shiro框架,我想知道大家是如何保存登录用户信息的,以前不用Shiro的时候存放在Session中, 现在我是如下方法获取登录用户信息: ![图片说明](https://img-ask.csdn.net/upload/201709/03/1504418815_668070.png) 但是获取的是null,这是我的realm代码,按道理应该已经吧user存储起来了才对: ![图片说明](https://img-ask.csdn.net/upload/201709/03/1504418864_246032.png) ,但是就是获取不到,存在Shiro的Session里面也是获取不到,请问呢保存用户信息是需要自己实现还是Shiro框架已经实现,如何实现呢? 感谢!

整合shiro报错:SessionFactory冲突

1、在配置shiro的配置文件的时候报错,查出原因就是下面这行导致的 <bean id="shiroSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"></bean> 报错信息: Cannot convert value of type [org.hibernate.impl.SessionFactoryImpl] to required type [org.apache.shiro.session.mgt.SessionFactory] for property 'sessionFactory': no matching editors or conversion strategy found 应该是shiro中也定义了属性SessionFactory,但是注入的却是hibernate的sessionfactory 怎么解决呢 求教!!!!

shiro 结合 ajax 返回 json 的解决方案

这个是我的shiro配置文件 ``` <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"> <!-- shiro的第三步 spring文件里面配置Shiro--> <!-- 3.1 配置SecurityManager 安全管理器--> <!-- SecurityManager : 安全管理器,主体认证和授权都是通过SecurityManager进行--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 3.1.1 注入 cacheManager 缓存管理器 --> <property name="cacheManager" ref="cacheManager" /> <!-- 3.1.2 注入 authenticator 属性赋值(下面会配置这个属性)--> <property name="authenticator" ref="authenticator"/> <!-- realm 域:相当于数据源,通过realm存取认证,授权相关数据 --> <property name="realms"> <list> <!-- 加载一个自定义的realm --> <ref bean="jdbcRealm"/> </list> </property> <!-- 记住我 的时间长--> <property name="rememberMeManager.cookie.maxAge" value="100"></property> </bean> <!-- 3.2配置cacheManager 缓存管理器 --> <!-- 3.2.1需要加入ehcache的jar包 + ehcache.xml配置文件 --> <!-- cacheManager : 缓存管理器,主要针对session和授权数据进行缓存 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <!-- 将数据通过 cacheManager + ehcache整合对缓存数据进行管理--> <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml" /> </bean> <!-- 3.3 配置 authenticator 认证器:主体进行认证最终通过authenticator进行 --> <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean> </property> </bean> <!-- shiro第四步配置自定义realm --> <!-- realm : 域,相当于数据源 ,通过realm存取认证,授权相关数据 --> <!-- 4.1配置Realm + 重写Realm类--> <bean id="jdbcRealm" class="com.leon.ssms.shiro.ShiroRealm"> <!-- 4.2 MD5加密配置 --> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="MD5"></property> <property name="hashIterations" value="1024"></property> </bean> </property> </bean> <!-- shiro第五步 配置LifecycleBeanPostProcessor --> <!-- 5.配置LifecycleBeanPostProcessor 可以自动的来调用配置在Spring IOC 容器中 shiro bean 的生命周期方法。 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- shiro第六步 启用IOC容器中 使用shiro注解--> <!-- 6.启用IOC容器中 使用shiro注解。但必须在配置lifecycleBeanPostProcessor 之后在可以使用。 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor" /> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <!-- shiro第七步 配置shiroFilter--> <!-- 7.1 id必须和web.xml文件中配置的DelegatingFilterProxy 的<filter-name>一致 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 登录页面 ,用户 登录不成功自动 返回该页面 --> <property name="loginUrl" value="/login.jsp"/> <!-- 登录成功页面,登录成功后跳转到该页面 --> <property name="successUrl" value="/home.action" /> <!-- 无权访问跳转页面 --> <property name="unauthorizedUrl" value="/unauthorized.action"/> <!-- 7.2 配置 filterChainDefinitionMap 属性 --> <!-- 将原先写死的认证和权限数据通过 Map的Key和Value的形式通过实例工厂类方法从数据库获取 --> <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"/> <!-- 配置哪些页面需要受保护以及访问这些页面需要的权限 --> <!-- 1).anon 可以匿名访问 2).autch 必须认证(需要登录)后才可以访问的页面 3).logout 登出 4).roles 角色权限 <property name="filterChainDefinitions"> <value> /login.jsp = anon /user/login.action = anon /user/logout.action = logout /user.jsp = roles[user] /admin.jsp = roles[admin] /** = authc </value> </property>--> </bean> <!-- 配置一个 bean, 该 bean 实际上是一个 Map. 通过实例工厂方法的方式 --> <bean id="filterChainDefinitionMap" factory-bean="FilterChainDefinitionMapBuilder" factory-method="builderFilterChainDefinitionMap"> </bean> <bean id="FilterChainDefinitionMapBuilder" class="com.leon.ssms.factory.FilterChainDefinitionMapBuilder"> </bean> </beans> ```

Shiro 操作数据库认证时报空指针

查询数据库进行用户验证时一直报错,如果去掉的话,可以正常执行 ``` @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken; String username = usernamePasswordToken.getUsername(); String s = String.valueOf(usernamePasswordToken.getPassword()); System.out.println(username); System.out.println(s); User user = userService.selectByUsername(username); return new SimpleAuthenticationInfo(username, "83ab58f3c2bf3778b78387cd8f6d508a7223a8f8955445751ee681feb2156959",ByteSource.Util.bytes(username),getName()); } ``` ``` java.lang.NullPointerException: null at com.jiyx.util.MyshiroRealm.doGetAuthenticationInfo(MyshiroRealm.java:49) ~[classes/:na] at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:568) ~[shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180) ~[shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:267) ~[shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198) ~[shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106) [shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:270) [shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:256) [shiro-core-1.2.5.jar:1.2.5] at com.jiyx.controller.CodeController.login(CodeController.java:71) [classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_152] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_152] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_152] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_152] at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851) [spring-webmvc-5.0.6.RELEASE.jar:5.0.6.RELEASE] at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) [shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) [shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) [shiro-core-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) [shiro-web-1.2.5.jar:1.2.5] at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) [shiro-web-1.2.5.jar:1.2.5] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468) [tomcat-embed-core-8.5.31.jar:8.5.31] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.31.jar:8.5.31] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_152] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_152] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.31.jar:8.5.31] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_152] ``` 问题解决了 ``` @Service public class UserServiceImpl implements UserService { @Resource UserMapper userMapper; @Override public User selectByUsername(String username) { return userMapper.selectByUsername(username); } } ``` Realm注入时改成如下 ``` private static UserService userService; @Autowired public void setSecurityService(UserService userService) { this.userService = userService; } ``` 网上搜了一下 我也遇到了,在controller中使用@Autowire注入是OK的,偏偏在Realm中无法注入,原因是配置了shiroFilter过滤器,spring会首先执行过滤器,此时spring bean还没有加载进来,导致bean为空,不知道楼主解决了没有。 但是搜了一下Bean的生命周期,没有说shiro Bean 这一块Bean是怎么初始化的 可以具体看下 https://www.cnblogs.com/ASPNET2008/p/5507269.html

2019 Python开发者日-培训

2019 Python开发者日-培训

150讲轻松搞定Python网络爬虫

150讲轻松搞定Python网络爬虫

设计模式(JAVA语言实现)--20种设计模式附带源码

设计模式(JAVA语言实现)--20种设计模式附带源码

YOLOv3目标检测实战:训练自己的数据集

YOLOv3目标检测实战:训练自己的数据集

java后台+微信小程序 实现完整的点餐系统

java后台+微信小程序 实现完整的点餐系统

三个项目玩转深度学习(附1G源码)

三个项目玩转深度学习(附1G源码)

初级玩转Linux+Ubuntu(嵌入式开发基础课程)

初级玩转Linux+Ubuntu(嵌入式开发基础课程)

2019 AI开发者大会

2019 AI开发者大会

玩转Linux:常用命令实例指南

玩转Linux:常用命令实例指南

一学即懂的计算机视觉(第一季)

一学即懂的计算机视觉(第一季)

4小时玩转微信小程序——基础入门与微信支付实战

4小时玩转微信小程序——基础入门与微信支付实战

Git 实用技巧

Git 实用技巧

Python数据清洗实战入门

Python数据清洗实战入门

使用TensorFlow+keras快速构建图像分类模型

使用TensorFlow+keras快速构建图像分类模型

实用主义学Python(小白也容易上手的Python实用案例)

实用主义学Python(小白也容易上手的Python实用案例)

程序员的算法通关课:知己知彼(第一季)

程序员的算法通关课:知己知彼(第一季)

MySQL数据库从入门到实战应用

MySQL数据库从入门到实战应用

机器学习初学者必会的案例精讲

机器学习初学者必会的案例精讲

手把手实现Java图书管理系统(附源码)

手把手实现Java图书管理系统(附源码)

极简JAVA学习营第四期(报名以后加助教微信:eduxy-1)

极简JAVA学习营第四期(报名以后加助教微信:eduxy-1)

.net core快速开发框架

.net core快速开发框架

玩转Python-Python3基础入门

玩转Python-Python3基础入门

Python数据挖掘简易入门

Python数据挖掘简易入门

微信公众平台开发入门

微信公众平台开发入门

程序员的兼职技能课

程序员的兼职技能课

Windows版YOLOv4目标检测实战:训练自己的数据集

Windows版YOLOv4目标检测实战:训练自己的数据集

HoloLens2开发入门教程

HoloLens2开发入门教程

微信小程序开发实战

微信小程序开发实战

Java8零基础入门视频教程

Java8零基础入门视频教程

相关热词 c# 解析cad c#数字格式化万 c#int转byte c#格式化日期 c# wpf 表格 c# 实现ad域验证登录 c#心跳包机制 c#使用fmod.dll c#dll vb 调用 c# outlook
立即提问
相关内容推荐