pom。?xmlversion1。0encodingUTF8?projectxmlnshttp:maven。apache。orgPOM4。0。0xmlns:xsihttp:www。w3。org2001XMLSchemainstancexsi:schemaLocationhttp:maven。apache。orgPOM4。0。0http:maven。apache。orgxsdmaven4。0。0。xsdmodelVersion4。0。0modelVersiongroupIdcom。examplegroupIddemoartifactIdversion0。0。1SNAPSHOTversionpackagingjarpackagingnamedemonamedescriptionDemoprojectforSpringBootdescriptionparentgroupIdorg。springframework。bootgroupIdspringbootstarterparentartifactIdversion2。0。3。RELEASEversionrelativePath!lookupparentfromrepositoryparentpropertiesproject。build。sourceEncodingUTF8project。build。sourceEncodingproject。reporting。outputEncodingUTF8project。reporting。outputEncodingjava。version1。8java。versionpropertiesdependenciesdependencygroupIdorg。springframework。bootgroupIdspringbootstarterdataredisartifactIddependencydependencygroupIdorg。springframework。bootgroupIdspringbootstarterthymeleafartifactIddependencydependencygroupIdorg。springframework。bootgroupIdspringbootstarterwebartifactIddependency!https:mvnrepository。comartifactorg。apache。shiroshiroalldependencygroupIdorg。apache。shirogroupIdshiroallartifactIdversion1。3。2versiondependency!https:mvnrepository。comartifactcom。alibabafastjsondependencygroupIdcom。alibabagroupIdfastjsonartifactIdversion1。2。47versiondependency!https:mvnrepository。comartifactorg。crazycakeshiroredisdependencygroupIdorg。crazycakegroupIdshiroredisartifactIdversion3。1。0versiondependencydependencygroupIdorg。springframework。bootgroupIdspringbootdevtoolsartifactIdscoperuntimescopedependencydependencygroupIdorg。springframework。bootgroupIdspringbootstartertestartifactIdscopetestscopedependencydependenciesbuildpluginsplugingroupIdorg。springframework。bootgroupIdspringbootmavenpluginartifactIdpluginplugingroupIdorg。apache。maven。pluginsgroupIdmavencompilerpluginartifactIdversion3。7。0versionconfigurationsource1。8sourcetarget1。8targetconfigurationpluginpluginsbuildproject redis配置文件packagecom。example。demo。importorg。springframework。beans。factory。annotation。Vimportorg。springframework。context。annotation。Cimportorg。springframework。context。annotation。PropertySConfigurationPropertySource(classpath:confredis。properties)publicclassRedisConfig{Value({shiro。redis。host})privateSValue({shiro。redis。timeout})publicStringgetHost(){}publicvoidsetHost(Stringhost){this。}publicintgetTimeout(){}publicvoidsetTimeout(inttimeout){this。}} Shiro配置文件packagecom。example。demo。importcom。example。demo。auth。PermissionRimportcom。example。demo。common。entity。Uimportorg。apache。shiro。authc。credential。HashedCredentialsMimportorg。apache。shiro。realm。AuthorizingRimportorg。apache。shiro。session。mgt。eis。JavaUuidSessionIdGimportorg。apache。shiro。spring。LifecycleBeanPostPimportorg。apache。shiro。spring。web。ShiroFilterFactoryBimportorg。apache。shiro。web。mgt。DefaultWebSecurityMimportorg。apache。shiro。web。servlet。SimpleCimportorg。apache。shiro。web。session。mgt。DefaultWebSessionMimportorg。crazycake。shiro。RedisCacheMimportorg。crazycake。shiro。RedisMimportorg。crazycake。shiro。RedisSessionDAO;importorg。springframework。aop。framework。autoproxy。DefaultAdvisorAutoProxyCimportorg。springframework。context。annotation。Bimportorg。springframework。context。annotation。Cimportorg。springframework。context。annotation。DependsOn;importorg。springframework。data。redis。connection。RedisConnectionFimportorg。springframework。data。redis。core。RedisTimportorg。springframework。data。redis。serializer。Jackson2JsonRedisSimportorg。springframework。data。redis。serializer。StringRedisSimportjava。util。LinkedHashMConfigurationpublicclassShiroConfig{BeanpublicRedisConfigredisConfig(){returnnewRedisConfig();}BeanpublicRedisManagerredisManager(){RedisManagerredisManagernewRedisManager();crazycake实现redisManager。setHost(redisConfig()。getHost());redisManager。setTimeout(redisConfig()。getTimeout());returnredisM}BeanpublicJavaUuidSessionIdGeneratorsessionIdGenerator(){returnnewJavaUuidSessionIdGenerator();}BeanpublicRedisSessionDAOsessionDAO(){RedisSessionDAOsessionDAOnewRedisSessionDAO();crazycake实现sessionDAO。setRedisManager(redisManager());sessionDAO。setSessionIdGenerator(sessionIdGenerator());SessionID生成器returnsessionDAO;}BeanpublicSimpleCookiecookie(){SimpleCookiecookienewSimpleCookie(SHAREJSESSIONID);cookie的name,对应的默认是JSESSIONIDcookie。setHttpOnly(true);cookie。setPath();path为用于多个系统共享JSESSIONID}BeanpublicDefaultWebSessionManagersessionManager(){DefaultWebSessionManagersessionManagernewDefaultWebSessionManager();sessionManager。setGlobalSessionTimeout(redisConfig()。getTimeout());设置session超时sessionManager。setDeleteInvalidSessions(true);删除无效sessionsessionManager。setSessionIdCookie(cookie());设置JSESSIONIDsessionManager。setSessionDAO(sessionDAO());设置sessionDAOreturnsessionM}1。配置SecurityManagerreturnBeanpublicDefaultWebSecurityManagersecurityManager(){DefaultWebSecurityManagersecurityManagernewDefaultWebSecurityManager();securityManager。setRealm(realm());设置realmsecurityManager。setSessionManager(sessionManager());设置sessionManagersecurityManager。setCacheManager(redisCacheManager());配置缓存的话,退出登录的时候crazycake会报错,要求放在session里面的实体类必须有个id标识returnsecurityM}2。配置缓存returnBeanpublicCacheManagercacheManager(){EhCacheManagerehCacheManagernewEhCacheManager();ehCacheManager。setCacheManagerConfigFile(classpath:ehcache。xml);returnehCacheM}BeanpublicRedisCacheManagerredisCacheManager(){RedisCacheManagercacheManagernewRedisCacheManager();crazycake实现cacheManager。setRedisManager(redisManager());returncacheM}3。配置RealmreturnBeanpublicAuthorizingRealmrealm(){PermissionRealmrealmnewPermissionRealm();HashedCredentialsMatchermatchernewHashedCredentialsMatcher();指定加密算法matcher。setHashAlgorithmName(MD5);指定加密次数matcher。setHashIterations(10);指定这个就不会报错matcher。setStoredCredentialsHexEncoded(true);realm。setCredentialsMatcher(matcher);}4。配置LifecycleBeanPostProcessor,可以来自动的调用配置在SpringIOC容器中ShiroBean的生命周期方法returnBeanpublicLifecycleBeanPostProcessorlifecycleBeanPostProcessor(){returnnewLifecycleBeanPostProcessor();}5。启用IOC容器中使用Shiro的注解,但是必须配置第四步才可以使用returnBeanDependsOn(lifecycleBeanPostProcessor)publicDefaultAdvisorAutoProxyCreatordefaultAdvisorAutoProxyCreator(){returnnewDefaultAdvisorAutoProxyCreator();}6。配置ShiroFilterreturnBeanpublicShiroFilterFactoryBeanshiroFilterFactoryBean(){LinkedHashMapString,StringmapnewLinkedHashMap();静态资源map。put(css,anon);map。put(js,anon);公共路径map。put(login,anon);map。put(register,anon);map。put(,anon);登出,项目中没有logout路径,因为shiro是过滤器,而SpringMVC是Servlet,Shiro会先执行map。put(logout,logout);授权map。put(user,authc,roles〔user〕);map。put(admin,authc,roles〔admin〕);everythingelserequiresauthentication:map。put(,authc);ShiroFilterFactoryBeanfactoryBeannewShiroFilterFactoryBean();配置SecurityManagerfactoryBean。setSecurityManager(securityManager());配置权限路径factoryBean。setFilterChainDefinitionMap(map);配置登录urlfactoryBean。setLoginUrl();配置无权限路径factoryBean。setUnauthorizedUrl(unauthorized);returnfactoryB}配置RedisTemplate,充当数据库服务returnBeanpublicRedisTemplateString,UserredisTemplate(RedisConnectionFactoryconnectionFactory){RedisTemplateString,UserredisTemplatenewRedisTemplate();redisTemplate。setConnectionFactory(connectionFactory);redisTemplate。setKeySerializer(newStringRedisSerializer());redisTemplate。setValueSerializer(newJackson2JsonRedisSerializerUser(User。class));returnredisT}} UserServicepackagecom。example。demo。importcom。example。demo。common。entity。Uimportjava。util。LpublicinterfaceUserService{voidaddUser(Useruser);Userlogin(Useruser);ListUsergetUsers();} implpackagecom。example。demo。service。importcom。example。demo。common。PasswordUimportcom。example。demo。common。entity。Uimportcom。example。demo。service。UserSimportorg。springframework。beans。factory。annotation。Aimportorg。springframework。data。redis。core。RedisTimportorg。springframework。stereotype。Simportjava。util。ArrayLimportjava。util。LServicepublicclassUserServiceImplimplementsUserService{AutowiredprivateRedisTemplateString,UserredisTOverridepublicvoidaddUser(Useruser){user。setPassword(PasswordUtils。saltAndMd5(user。getUsername(),user。getPassword()));加密redisTemplate。boundHashOps(users)。put(user。getUsername(),user);}OverridepublicUserlogin(Useruser){user。setPassword(PasswordUtils。saltAndMd5(user。getUsername(),user。getPassword()));加密Useru(User)redisTemplate。boundHashOps(users)。get(user。getUsername());if(unull!check(user,u)){}}OverridepublicListUsergetUsers(){ListObjectlistredisTemplate。boundHashOps(users)。values();ListUserusersnewArrayList();list。forEach(u{users。add((User)u);});}privatebooleancheck(Usera,Userb){if(a。getUsername()。equals(b。getUsername())a。getPassword()。equals(b。getPassword())){}}} controllerpackagecom。example。demo。importcom。example。demo。common。entity。Uimportcom。example。demo。common。response。BaseRimportcom。example。demo。service。UserSimportorg。apache。shiro。SecurityUimportorg。apache。shiro。authc。UsernamePasswordTimportorg。apache。shiro。subject。Simportorg。springframework。beans。factory。annotation。Aimportorg。springframework。web。bind。annotation。RequestBimportorg。springframework。web。bind。annotation。RequestMimportorg。springframework。web。bind。annotation。RestCimportorg。springframework。web。servlet。ModelAndVRestControllerpublicclassSimpleController{AutowiredprivateUserServiceuserSRequestMapping()publicModelAndViewindex(){returnnewModelAndView(index);}RequestMapping(login)publicBaseResponseStringlogin(RequestBodyUseruser){BaseResponseStringresponsenewBaseResponse(0,登陆成功);SubjectsubjectSecurityUtils。getSubject();UsernamePasswordTokentokennewUsernamePasswordToken(user。getUsername(),user。getPassword());subject。login(token);response。setData(home);}RequestMapping(register)publicBaseResponseregister(RequestBodyUseruser){userService。addUser(user);returnnewBaseResponse(0,注册成功);}RequestMapping(home)publicModelAndViewhome(){ModelAndViewmvnewModelAndView(home);mv。addObject(users,userService。getUsers());}} redis。propertiesshiro。redis。hostlocalhost:6379shiro。redis。timeout1800000 applicatin。propertiesserver。port8080server。port8081server。port8082spring。redis。host127。0。0。1spring。redis。port6379 index。html!DOCTYPEhtmlhtmllangenxmlns:thhttp:www。thymeleaf。orgheadmetacharsetUTF8titleIndextitlelinkth:href{cssindex。css}relstylesheettypetextcssheadbodyh2初级SpringBootShiro小栗子NodeOneh2!h2初级SpringBootShiro小栗子NodeTwoh2inputtypetextnameusernameplaceholder请输入用户名inputtypepasswordnamepasswordplaceholder请输入密码登录点我!不登录进不去inputtypetextnameusernameplaceholder请输入用户名inputtypepasswordnamepasswordplaceholder请输入密码inputtypetextnameshowplaceholder自我介绍注册!!似懂非懂!bodyhtml home。html!DOCTYPEhtmlhtmllangenxmlns:thhttp:www。thymeleaf。orgheadmetacharsetUTF8titleHometitlelinkth:href{cssindex。css}relstylesheettypetextcssheadbodyh2初级SpringBootShiro小栗子NodeOneh2!h2初级SpringBootShiro小栗子NodeTwoh2退出登录tableclasstabletheadtrthUsernameththPasswordththShowthtrtheadtbodytrth:eachu:{users}td〔〔{u。username}〕〕tdtd〔〔{u。password}〕〕tdtd〔〔{u。show}〕〕tdtrtbodytablebodyhtml 以上两种配置各打包一次(记得留着打包好的jar包) 解压到无中文目录,修改Nginx配置文件 upstreammyapp{server127。0。0。1:8081weight1;server127。0。0。1:8082weight1;}server{listen80;location{proxypasshttp:proxysetheaderHproxysetheaderXRealIPproxysetheaderXForwardedF}} 到此,先启动两个jar包(分别是8081,NodeO8082,NodeTwo) 然后启动Nginx 浏览器访问:http:localhost 刷新看看。。 随便在一个节点上注册,登录,然后刷新到另外一个节点,发现不用登录就可以访问权限资源 。。 github地址:https:github。comzhiyongzhaobootshirosession