├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── UPDATE.md ├── pom.xml └── src ├── doc └── table.sql ├── main ├── java │ └── club │ │ └── yuit │ │ ├── CodeGenerator.java │ │ └── oauth │ │ └── boot │ │ ├── BootApplication.java │ │ ├── authentication │ │ └── sms │ │ │ ├── SmsAuthenticationProvider.java │ │ │ ├── SmsCodeAuthenticationFilter.java │ │ │ ├── SmsCodeAuthenticationToken.java │ │ │ ├── SmsCodeCheckFilter.java │ │ │ └── SmsSecurityConfig.java │ │ ├── config │ │ ├── CoreConfig.java │ │ ├── DbConfig.java │ │ ├── RedisConfig.java │ │ ├── SecurityConfig.java │ │ └── auth2 │ │ │ ├── OAuth2AuthorizationServerConfig.java │ │ │ ├── OAuth2ResourceServerConfig.java │ │ │ └── TokenStoreConfig.java │ │ ├── controller │ │ ├── BaseMainController.java │ │ ├── BootGrantController.java │ │ ├── ClientController.java │ │ ├── CodeController.java │ │ └── TestController.java │ │ ├── entity │ │ ├── Client.java │ │ └── User.java │ │ ├── exception │ │ ├── ArgumentsFailureException.java │ │ ├── AuthFailureException.java │ │ ├── NotAuthException.java │ │ ├── NotAuthorityException.java │ │ └── VerificationCodeFailureException.java │ │ ├── filter │ │ ├── BootBasicAuthenticationFilter.java │ │ └── BootPictureCodeAuthenticationFilter.java │ │ ├── handler │ │ ├── BootLoginFailureHandler.java │ │ └── ExceptionAdviceHandler.java │ │ ├── mapper │ │ ├── ClientMapper.java │ │ └── UserMapper.java │ │ ├── response │ │ ├── BaseResponse.java │ │ ├── HttpResponse.java │ │ ├── HttpStatusAndMsg.java │ │ ├── Items.java │ │ ├── ListResponse.java │ │ ├── OrderType.java │ │ ├── PageAndSortResponse.java │ │ ├── PageQueryItems.java │ │ └── SimpleResponse.java │ │ ├── service │ │ ├── IClientService.java │ │ ├── IUserService.java │ │ └── impl │ │ │ ├── ClientServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ ├── support │ │ ├── BootSecurityProperties.java │ │ ├── BootSmsUserDetailService.java │ │ ├── BootUserDetailService.java │ │ ├── DefaultBeanName.java │ │ ├── code │ │ │ ├── BootCodeService.java │ │ │ ├── RedisCodeService.java │ │ │ ├── SessionCodeService.java │ │ │ ├── VerificationCode.java │ │ │ ├── VerificationCodeGenerator.java │ │ │ ├── picture │ │ │ │ └── DefaultPictureCodeGenerator.java │ │ │ └── sms │ │ │ │ └── DefaultSmsCodeGenerator.java │ │ ├── common │ │ │ └── TokenStoreType.java │ │ ├── oauth2 │ │ │ ├── BootAccessDeniedHandler.java │ │ │ ├── BootClientDetails.java │ │ │ ├── BootClientDetailsService.java │ │ │ ├── BootOAuth2AuthExceptionEntryPoint.java │ │ │ ├── BootOAuth2Exception.java │ │ │ ├── BootOAuth2WebResponseExceptionTranslator.java │ │ │ └── BootOAuthExceptionJacksonSerializer.java │ │ └── properities │ │ │ ├── BootBaseLoginProperties.java │ │ │ ├── BootLogLevelProperties.java │ │ │ ├── BootOAuth2Properties.java │ │ │ ├── BootSmsLoginProperties.java │ │ │ └── CodeStoreType.java │ │ └── utils │ │ ├── CommonUtils.java │ │ └── HttpUtils.java └── resources │ ├── application.yml │ ├── mapper │ └── UserMapper.xml │ ├── statics │ ├── favicon.png │ ├── libs │ │ ├── layer │ │ │ ├── layer.js │ │ │ └── theme │ │ │ │ └── default │ │ │ │ ├── icon-ext.png │ │ │ │ ├── icon.png │ │ │ │ ├── layer.css │ │ │ │ ├── loading-0.gif │ │ │ │ ├── loading-1.gif │ │ │ │ └── loading-2.gif │ │ └── now-ui │ │ │ ├── css │ │ │ ├── bootstrap.min.css │ │ │ ├── now-ui-kit.css │ │ │ └── now-ui-kit.min.css │ │ │ ├── fonts │ │ │ ├── nucleo-license.md │ │ │ ├── nucleo-outline.eot │ │ │ ├── nucleo-outline.ttf │ │ │ ├── nucleo-outline.woff │ │ │ └── nucleo-outline.woff2 │ │ │ ├── img │ │ │ ├── apple-icon.png │ │ │ ├── avatar.jpg │ │ │ ├── bg1.jpg │ │ │ ├── bg11.jpg │ │ │ ├── bg3.jpg │ │ │ ├── bg4.jpg │ │ │ ├── bg5.jpg │ │ │ ├── bg6.jpg │ │ │ ├── bg7.jpg │ │ │ ├── bg8.jpg │ │ │ ├── blurred-image-1.jpg │ │ │ ├── creative-tim-white-slim2.png │ │ │ ├── default-avatar.png │ │ │ ├── eva.jpg │ │ │ ├── favicon.png │ │ │ ├── flags │ │ │ │ ├── AD.png │ │ │ │ ├── AE.png │ │ │ │ ├── AG.png │ │ │ │ ├── AM.png │ │ │ │ ├── AR.png │ │ │ │ ├── AT.png │ │ │ │ ├── AU.png │ │ │ │ ├── BE.png │ │ │ │ ├── BF.png │ │ │ │ ├── BG.png │ │ │ │ ├── BO.png │ │ │ │ ├── BR.png │ │ │ │ ├── CA.png │ │ │ │ ├── CD.png │ │ │ │ ├── CG.png │ │ │ │ ├── CH.png │ │ │ │ ├── CL.png │ │ │ │ ├── CM.png │ │ │ │ ├── CN.png │ │ │ │ ├── CO.png │ │ │ │ ├── CZ.png │ │ │ │ ├── DE.png │ │ │ │ ├── DJ.png │ │ │ │ ├── DK.png │ │ │ │ ├── DZ.png │ │ │ │ ├── EE.png │ │ │ │ ├── EG.png │ │ │ │ ├── ES.png │ │ │ │ ├── FI.png │ │ │ │ ├── FR.png │ │ │ │ ├── GA.png │ │ │ │ ├── GB.png │ │ │ │ ├── GM.png │ │ │ │ ├── GT.png │ │ │ │ ├── HN.png │ │ │ │ ├── HT.png │ │ │ │ ├── HU.png │ │ │ │ ├── ID.png │ │ │ │ ├── IE.png │ │ │ │ ├── IL.png │ │ │ │ ├── IN.png │ │ │ │ ├── IQ.png │ │ │ │ ├── IR.png │ │ │ │ ├── IT.png │ │ │ │ ├── JM.png │ │ │ │ ├── JO.png │ │ │ │ ├── JP.png │ │ │ │ ├── KG.png │ │ │ │ ├── KN.png │ │ │ │ ├── KP.png │ │ │ │ ├── KR.png │ │ │ │ ├── KW.png │ │ │ │ ├── KZ.png │ │ │ │ ├── LA.png │ │ │ │ ├── LB.png │ │ │ │ ├── LC.png │ │ │ │ ├── LS.png │ │ │ │ ├── LU.png │ │ │ │ ├── LV.png │ │ │ │ ├── MG.png │ │ │ │ ├── MK.png │ │ │ │ ├── ML.png │ │ │ │ ├── MM.png │ │ │ │ ├── MT.png │ │ │ │ ├── MX.png │ │ │ │ ├── NA.png │ │ │ │ ├── NE.png │ │ │ │ ├── NG.png │ │ │ │ ├── NI.png │ │ │ │ ├── NL.png │ │ │ │ ├── NO.png │ │ │ │ ├── OM.png │ │ │ │ ├── PA.png │ │ │ │ ├── PE.png │ │ │ │ ├── PG.png │ │ │ │ ├── PK.png │ │ │ │ ├── PL.png │ │ │ │ ├── PT.png │ │ │ │ ├── PY.png │ │ │ │ ├── QA.png │ │ │ │ ├── RO.png │ │ │ │ ├── RU.png │ │ │ │ ├── RW.png │ │ │ │ ├── SA.png │ │ │ │ ├── SE.png │ │ │ │ ├── SG.png │ │ │ │ ├── SL.png │ │ │ │ ├── SN.png │ │ │ │ ├── SO.png │ │ │ │ ├── SV.png │ │ │ │ ├── TD.png │ │ │ │ ├── TJ.png │ │ │ │ ├── TL.png │ │ │ │ ├── TR.png │ │ │ │ ├── TZ.png │ │ │ │ ├── UA.png │ │ │ │ ├── US.png │ │ │ │ ├── VE.png │ │ │ │ ├── VN.png │ │ │ │ └── YE.png │ │ │ ├── header.jpg │ │ │ ├── hero-image-1.png │ │ │ ├── hero-image-2.png │ │ │ ├── hero-image-3.png │ │ │ ├── invision-white-slim.png │ │ │ ├── julie.jpg │ │ │ ├── landing.jpg │ │ │ ├── login.jpg │ │ │ ├── logo-square.jpg │ │ │ ├── logo.png │ │ │ ├── now-logo.png │ │ │ ├── nucleo-logo.svg │ │ │ ├── profile.jpg │ │ │ └── ryan.jpg │ │ │ └── js │ │ │ ├── core │ │ │ ├── bootstrap.min.js │ │ │ ├── jquery.min.js │ │ │ └── popper.min.js │ │ │ ├── now-ui-kit.js │ │ │ ├── now-ui-kit.js.map │ │ │ ├── now-ui-kit.min.js │ │ │ └── plugins │ │ │ ├── bootstrap-datepicker.js │ │ │ ├── bootstrap-switch.js │ │ │ └── nouislider.min.js │ └── styles │ │ ├── base-grant.css │ │ ├── base-login.css │ │ └── base.css │ └── views │ ├── base-grant.html │ ├── base-login.html │ └── commons │ └── head.html └── test └── java ├── Main.java └── club └── yuit └── oauth └── boot └── BootApplicationTests.java /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=java 2 | *.css linguist-language=java 3 | *.html linguist-language=java 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 yuit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### OAUTH-BOOT 2 | 3 | spring-security ,spring-security-oauth2 ,string boot 学习 4 | 5 | --- 6 | 7 | #### Update 8 | [更新说明](https://github.com/LookBackInTheRain/oauth-boot/blob/dev/UPDATE.md) 9 | #### Current 10 | 1. 授权码模式,密码模式,简化模式(未测试),客户端模式(未测试) 11 | 2. JWT 12 | 3. 自定义登录页面和授权页面 13 | 4. 自定义异常处理 14 | 5. [认证服务与资源服务分离](https://github.com/LookBackInTheRain/oauth-boot-up) 15 | 16 | #### 配置 17 | 18 | ```yaml 19 | boot: 20 | oauth: 21 | # token 存储方式,可选配置 22 | token-store-type: jwt #默认为 memory 23 | # token签名秘钥,可选配置,默认:OAUTHBOOT@IUY09&098#UIOKNJJ-YUIT.CLUB 24 | token-signing-key: 123qwe 25 | # 登录处理url 可选配置 26 | login-process-url: /auth/authorize 27 | ``` 28 | 29 | #### 授权码模式 30 | 31 | 1. 请求授权 http://ip:port/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://localhost:9000&scope=select 32 | 2. 如果没有登录会跳转到登录页面,登录后跳转到授权页面(是否会跳转到授权页面取决于是否将isAutoApprove字段的值 ) 33 | 3. 授权后得到一个授权码,拿着授权码即可申请token 34 | 35 | #### 密码模式 36 | 没有配置允许客户端表单登录的,将客户端id和密码base64编码放入请求头中,根据oauth2协议规定的密码模式正确填写参数即可申请token 37 | 38 | #### 依赖 39 | 40 | |框架/类库/数据库| 版本号 | 41 | |--|--| 42 | |java|11(Mac)/ 8(Win10)| 43 | | spring-boot | 2.0.5.RELEASE | 44 | |spring-security|5.0.8.RELEASE | 45 | |spring-security-oauth2-autoconfigure|2.0.6.RELEASE| 46 | |mybatis-plus|3.0.4| 47 | |数据库连接池(druid)|1.1.11| 48 | |swagger-ui|2.9.2| 49 | |hibernate-validator|6.0.13.Final| 50 | |MySQL|5.7.22 MySQL Community Server| 51 | |Redis|4.0.10| 52 | 53 | #### 项目效果 54 | 1. 自定义登录和授权页面效果图 55 | ![自定义登录和授权页面效果图](https://raw.githubusercontent.com/LookBackInTheRain/uit-blog/master/spring/OAuth2%E7%88%AC%E5%9D%91%E6%97%A5%E8%AE%B0/imgs/3/authorization.gif) 56 | 57 | #### 建表语句在src/doc/table.sql中 58 | 59 | 相关的测试数据也在这个sql文件中,加密的密码统一为123qwe 60 | 61 | #### 注 62 | 63 | 请使用上述依赖所规定的版本 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /UPDATE.md: -------------------------------------------------------------------------------- 1 | 2 | ### 2019/4/9 更新 3 | 1. [认证服务与资源服务分离](https://github.com/LookBackInTheRain/oauth-boot-up) 4 | ### 2019/3/8 更新 5 | 1. 解决无法使用 `refresh_token` 更新`token`问题 6 | 2. `spring-boot` 升级并测试通过 7 | 8 | |框架/类库/数据库| 旧版本 | 新版本| 9 | |--|--|--| 10 | |java|11(Mac)/ 8(Win10)| - | 11 | | spring-boot | 2.0.5.RELEASE | 2.1.3.RELEASE | 12 | |spring-security|5.0.8.RELEASE | 5.0.8.RELEASE | 13 | |spring-security-oauth2-autoconfigure|2.0.6.RELEASE| 2.1.3.RELEASE | 14 | |mybatis-plus|3.0.4| 3.1.0 | 15 | |数据库连接池(druid)|1.1.11| 1.1.14 | 16 | |swagger-ui|2.9.2| - | 17 | |hibernate-validator|6.0.13.Final| - | 18 | |MySQL|5.7.22 MySQL Community Server| - | 19 | |Redis|4.0.10| - | 20 | 21 | ### 2019/2/15 更新 22 | 1. 配置token存储类型增加jdbc,已测试通过 23 | ``` 24 | 使用jdbc时必须创建的表的SQL语句在/src/doc/table.sql中,建表语句参考 : 25 | https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql 26 | ``` 27 | 2. 修复 [#4](https://github.com/LookBackInTheRain/oauth-boot/issues/4) -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | club.yuit 7 | oauth-boot 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | oauth-boot 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.1.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | javax.xml.bind 34 | jaxb-api 35 | 2.3.1 36 | 37 | 38 | 39 | 40 | javax.activation 41 | activation 42 | 1.1 43 | 44 | 45 | 46 | org.glassfish.jaxb 47 | jaxb-runtime 48 | 2.3.1 49 | 50 | 51 | 52 | 53 | 54 | org.springframework.boot 55 | spring-boot-starter-web 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-security 61 | 62 | 63 | 64 | org.springframework.security 65 | spring-security-jwt 66 | 1.0.9.RELEASE 67 | 68 | 69 | 70 | 75 | 76 | 77 | org.springframework.security.oauth.boot 78 | spring-security-oauth2-autoconfigure 79 | 2.1.3.RELEASE 80 | 81 | 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-starter-data-redis 86 | 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-devtools 91 | runtime 92 | 93 | 94 | mysql 95 | mysql-connector-java 96 | runtime 97 | 98 | 99 | org.projectlombok 100 | lombok 101 | true 102 | 103 | 104 | 105 | org.springframework.boot 106 | spring-boot-starter-test 107 | test 108 | 109 | 110 | 111 | org.springframework.boot 112 | spring-boot-configuration-processor 113 | true 114 | 115 | 116 | 117 | 118 | com.baomidou 119 | mybatis-plus-boot-starter 120 | 3.1.0 121 | 122 | 123 | 124 | com.baomidou 125 | mybatis-plus-generator 126 | 3.1.0 127 | 128 | 129 | 130 | 131 | com.alibaba 132 | druid 133 | 1.1.14 134 | 135 | 136 | 137 | 138 | io.springfox 139 | springfox-swagger2 140 | 2.9.2 141 | 142 | 143 | 144 | io.springfox 145 | springfox-swagger-ui 146 | 2.9.2 147 | 148 | 149 | 150 | 151 | 152 | 153 | org.hibernate 154 | hibernate-validator 155 | 6.0.13.Final 156 | 157 | 158 | 159 | org.apache.commons 160 | commons-lang3 161 | 162 | 163 | 164 | org.springframework.boot 165 | spring-boot-starter-thymeleaf 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | org.springframework.boot 177 | spring-boot-maven-plugin 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /src/doc/table.sql: -------------------------------------------------------------------------------- 1 | use boot; 2 | 3 | -- 创建用户表 4 | create table user 5 | ( 6 | id varchar(32) primary key, 7 | username varchar(255), 8 | password varchar(255), 9 | gender varchar(10) , 10 | mobile varchar(16), 11 | email varchar(100), 12 | isEnable bit, 13 | isExpired bit, 14 | isLocked bit, 15 | createTime timestamp default current_timestamp comment '创建时间', 16 | modifyTime timestamp default current_timestamp on update current_timestamp comment '更新时间' 17 | ); 18 | 19 | -- 客户端表 20 | create table clients ( 21 | id varchar(32) primary key, 22 | clientId varchar(100) not null, 23 | resourceIds varchar(255), 24 | isSecretRequired bit, 25 | clientSecret varchar(100), 26 | isScoped bit, 27 | scope varchar(255), 28 | authorizedGrantTypes varchar(255) not null, 29 | registeredRedirectUri varchar(255) not null, 30 | authorities varchar(255), 31 | isAutoApprove bit, 32 | accessTokenValiditySeconds int , 33 | refreshTokenValiditySeconds int, 34 | createTime timestamp default current_timestamp comment '创建时间', 35 | modifyTime timestamp default current_timestamp on update current_timestamp comment '更新时间' 36 | ); 37 | 38 | -- user 测试数据 密码123qwe 39 | INSERT INTO boot.user (id, username,mobile, password, gender, email, isEnable, isExpired, isLocked) VALUES ('67842834823', 'admin','18785471131', '$2a$10$06S5v7Mo47e8Qyv65Ltz.uhcQwfhIcgYDKVPVzBlPj6UHWV2ErbzK', '女', '阿斯达@as.com', true, false, true); 40 | 41 | -- clients 测试数据 密码123qwe 42 | INSERT INTO boot.clients (id, clientId, resourceIds, isSecretRequired, clientSecret, isScoped, scope, authorizedGrantTypes, registeredRedirectUri, authorities, isAutoApprove, accessTokenValiditySeconds, refreshTokenValiditySeconds, createTime, modifyTime) VALUES ('JKGJHGJHFGH89867', 'client', 'boot-server', true, '$2a$10$06S5v7Mo47e8Qyv65Ltz.uhcQwfhIcgYDKVPVzBlPj6UHWV2ErbzK', true, 'select', 'refresh_token,authorization_code,password', 'http://localhost:9000', 'CLIENT,ADMIN', false, 1800, 36000, '2018-10-16 10:02:14', '2018-12-14 09:05:03'); 43 | 44 | 45 | -- 当token-store-type: jdbc时 需要创建如下两张表 46 | create table oauth_access_token 47 | ( 48 | token_id VARCHAR(255), 49 | token longblob, 50 | authentication_id VARCHAR(255) PRIMARY KEY, 51 | user_name VARCHAR(255), 52 | client_id VARCHAR(255), 53 | authentication longblob, 54 | refresh_token VARCHAR(255) 55 | ); 56 | 57 | create table oauth_refresh_token 58 | ( 59 | token_id VARCHAR(256), 60 | token longblob, 61 | authentication longblob 62 | ); 63 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/CodeGenerator.java: -------------------------------------------------------------------------------- 1 | package club.yuit; 2 | 3 | import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; 4 | import com.baomidou.mybatisplus.core.toolkit.StringPool; 5 | import com.baomidou.mybatisplus.core.toolkit.StringUtils; 6 | import com.baomidou.mybatisplus.generator.AutoGenerator; 7 | import com.baomidou.mybatisplus.generator.InjectionConfig; 8 | import com.baomidou.mybatisplus.generator.config.*; 9 | import com.baomidou.mybatisplus.generator.config.po.TableInfo; 10 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; 11 | import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Scanner; 16 | 17 | /** 18 | * @author yuit 19 | * @date 2018/10/9 17:24 20 | * 代码生成器 21 | **/ 22 | public class CodeGenerator { 23 | 24 | /** 25 | *

26 | * 读取控制台内容 27 | *

28 | */ 29 | public static String scanner(String tip) { 30 | Scanner scanner = new Scanner(System.in); 31 | StringBuilder help = new StringBuilder(); 32 | help.append("请输入" + tip + ":"); 33 | System.out.println(help.toString()); 34 | if (scanner.hasNext()) { 35 | String ipt = scanner.next(); 36 | if (StringUtils.isNotEmpty(ipt)) { 37 | return ipt; 38 | } 39 | } 40 | throw new MybatisPlusException("请输入正确的" + tip + "!"); 41 | } 42 | 43 | public static void main(String[] args) { 44 | // 代码生成器 45 | AutoGenerator mpg = new AutoGenerator(); 46 | 47 | 48 | // 全局配置 49 | GlobalConfig gc = new GlobalConfig(); 50 | String projectPath = System.getProperty("user.dir"); 51 | gc.setOutputDir(projectPath + "/src/main/java"); 52 | gc.setAuthor("jobob"); 53 | gc.setOpen(false); 54 | mpg.setGlobalConfig(gc); 55 | 56 | // 数据源配置 57 | DataSourceConfig dsc = new DataSourceConfig(); 58 | dsc.setUrl("jdbc:mysql://:3306/ant?useUnicode=true&useSSL=false&characterEncoding=utf8"); 59 | // dsc.setSchemaName("public"); 60 | dsc.setDriverName("com.mysql.jdbc.Driver"); 61 | dsc.setUsername("root"); 62 | dsc.setPassword("密码"); 63 | mpg.setDataSource(dsc); 64 | 65 | // 包配置 66 | PackageConfig pc = new PackageConfig(); 67 | pc.setModuleName(scanner("模块名")); 68 | pc.setParent("com.baomidou.ant"); 69 | mpg.setPackageInfo(pc); 70 | 71 | // 自定义配置 72 | InjectionConfig cfg = new InjectionConfig() { 73 | @Override 74 | public void initMap() { 75 | // to do nothing 76 | } 77 | }; 78 | List focList = new ArrayList<>(); 79 | focList.add(new FileOutConfig("/templates/mapper.xml.ftl") { 80 | @Override 81 | public String outputFile(TableInfo tableInfo) { 82 | // 自定义输入文件名称 83 | return projectPath + "/src/main/resources/mapper/" + pc.getModuleName() 84 | + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; 85 | } 86 | }); 87 | cfg.setFileOutConfigList(focList); 88 | mpg.setCfg(cfg); 89 | mpg.setTemplate(new TemplateConfig().setXml(null)); 90 | 91 | // 策略配置 92 | StrategyConfig strategy = new StrategyConfig(); 93 | strategy.setNaming(NamingStrategy.underline_to_camel); 94 | strategy.setColumnNaming(NamingStrategy.underline_to_camel); 95 | strategy.setSuperEntityClass("com.baomidou.ant.common.BaseEntity"); 96 | strategy.setEntityLombokModel(true); 97 | strategy.setRestControllerStyle(true); 98 | strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController"); 99 | strategy.setInclude(scanner("表名")); 100 | strategy.setSuperEntityColumns("id"); 101 | strategy.setControllerMappingHyphenStyle(true); 102 | strategy.setTablePrefix(pc.getModuleName() + "_"); 103 | mpg.setStrategy(strategy); 104 | mpg.setTemplateEngine(new FreemarkerTemplateEngine()); 105 | mpg.execute(); 106 | } 107 | 108 | 109 | } 110 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/BootApplication.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | 8 | /** 9 | * @author yuit 10 | */ 11 | @SpringBootApplication 12 | @MapperScan("club.yuit.oauth.boot.mapper") 13 | public class BootApplication { 14 | 15 | 16 | 17 | public static void main(String[] args) { 18 | ConfigurableApplicationContext context= SpringApplication.run(BootApplication.class, args); 19 | 20 | } 21 | 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/authentication/sms/SmsAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.authentication.sms; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.springframework.data.redis.core.StringRedisTemplate; 6 | import org.springframework.security.authentication.AuthenticationProvider; 7 | import org.springframework.security.authentication.InternalAuthenticationServiceException; 8 | import org.springframework.security.core.Authentication; 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | 13 | /** 14 | * @author yuit 15 | * @date 2018/10/19 15:33 16 | */ 17 | @Getter 18 | @Setter 19 | public class SmsAuthenticationProvider implements AuthenticationProvider { 20 | 21 | private UserDetailsService userDetailsService; 22 | 23 | 24 | public SmsAuthenticationProvider() { 25 | } 26 | 27 | @Override 28 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { 29 | 30 | SmsCodeAuthenticationToken authenticationToken = (SmsCodeAuthenticationToken) authentication; 31 | 32 | UserDetails user = this.userDetailsService.loadUserByUsername((String) authenticationToken.getPrincipal()); 33 | 34 | if (user == null) { 35 | throw new InternalAuthenticationServiceException("无法获取用户信息"); 36 | } 37 | 38 | SmsCodeAuthenticationToken authenticationResult = new SmsCodeAuthenticationToken(user,user.getAuthorities()); 39 | 40 | authenticationResult.setDetails(authenticationToken.getDetails()); 41 | 42 | return authenticationResult; 43 | } 44 | 45 | @Override 46 | public boolean supports(Class authentication) { 47 | return SmsCodeAuthenticationToken.class.isAssignableFrom(authentication); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/authentication/sms/SmsCodeAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.authentication.sms; 2 | 3 | import club.yuit.oauth.boot.support.BootSecurityProperties; 4 | import org.springframework.security.authentication.AuthenticationServiceException; 5 | import org.springframework.security.core.Authentication; 6 | import org.springframework.security.core.AuthenticationException; 7 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; 8 | import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 9 | import org.springframework.util.Assert; 10 | 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | 14 | /** 15 | * @author yuit 16 | * @date 2018/10/19 15:33 17 | */ 18 | public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter { 19 | 20 | 21 | public static final String BOOT_FORM_MOBILE_KEY = "mobile"; 22 | 23 | private String mobileParameter = BOOT_FORM_MOBILE_KEY; 24 | private boolean postOnly = true; 25 | 26 | 27 | public SmsCodeAuthenticationFilter(String path) { 28 | super(new AntPathRequestMatcher(path, "POST")); 29 | } 30 | 31 | // ~ Methods 32 | // ======================================================================================================== 33 | @Override 34 | public Authentication attemptAuthentication(HttpServletRequest request, 35 | HttpServletResponse response) throws AuthenticationException { 36 | if (postOnly && !request.getMethod().equalsIgnoreCase("POST")) { 37 | throw new AuthenticationServiceException( 38 | "Authentication method not supported: " + request.getMethod()); 39 | } 40 | 41 | String mobile = obtainMobile(request); 42 | 43 | 44 | if (mobile == null) { 45 | mobile = ""; 46 | } 47 | 48 | 49 | 50 | mobile = mobile.trim(); 51 | 52 | SmsCodeAuthenticationToken authRequest = new SmsCodeAuthenticationToken(mobile); 53 | 54 | // Allow subclasses to set the "details" property 55 | setDetails(request,authRequest); 56 | 57 | return this.getAuthenticationManager().authenticate(authRequest); 58 | } 59 | 60 | 61 | /** 62 | * 获取手机号 63 | * @param request 64 | * @return 65 | */ 66 | protected String obtainMobile(HttpServletRequest request) { 67 | return request.getParameter(mobileParameter); 68 | } 69 | 70 | /** 71 | * Provided so that subclasses may configure what is put into the authentication 72 | * request's details property. 73 | * 74 | * @param request that an authentication request is being created for 75 | * @param authRequest the authentication request object that should have its details 76 | * set 77 | */ 78 | protected void setDetails(HttpServletRequest request, 79 | SmsCodeAuthenticationToken authRequest) { 80 | authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); 81 | } 82 | 83 | /** 84 | * Sets the parameter name which will be used to obtain the username from the login 85 | * request. 86 | * 87 | * @param usernameParameter the parameter name. Defaults to "username". 88 | */ 89 | public void setMobileParameter(String usernameParameter) { 90 | Assert.hasText(usernameParameter, "Username parameter must not be empty or null"); 91 | this.mobileParameter = usernameParameter; 92 | } 93 | 94 | 95 | 96 | /** 97 | * Defines whether only HTTP POST requests will be allowed by this filter. If set to 98 | * true, and an authentication request is received which is not a POST request, an 99 | * exception will be raised immediately and authentication will not be attempted. The 100 | * unsuccessfulAuthentication() method will be called as if handling a failed 101 | * authentication. 102 | *

103 | * Defaults to true but may be overridden by subclasses. 104 | */ 105 | public void setPostOnly(boolean postOnly) { 106 | this.postOnly = postOnly; 107 | } 108 | 109 | public final String getMobileParameter() { 110 | return mobileParameter; 111 | } 112 | 113 | 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/authentication/sms/SmsCodeAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.authentication.sms; 2 | 3 | import org.springframework.security.authentication.AbstractAuthenticationToken; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.SpringSecurityCoreVersion; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * @author yuit 11 | * @date 2018/10/19 15:33 12 | */ 13 | public class SmsCodeAuthenticationToken extends AbstractAuthenticationToken { 14 | 15 | private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; 16 | 17 | // ~ Instance fields 18 | // ================================================================================================ 19 | 20 | private final Object principal; 21 | // 这里存放登录相关的信息,用户名,密码等,但是在认证之前已经把短信验证码校验过,这里不需要 22 | // private Object credentials; 23 | 24 | // ~ Constructors 25 | // =================================================================================================== 26 | 27 | /** 28 | * This constructor can be safely used by any code that wishes to create a 29 | * UsernamePasswordAuthenticationToken, as the {@link #isAuthenticated()} 30 | * will return false. 31 | * 32 | */ 33 | public SmsCodeAuthenticationToken(String mobile) { 34 | super(null); 35 | this.principal = mobile; 36 | setAuthenticated(false); 37 | } 38 | 39 | /** 40 | * This constructor should only be used by AuthenticationManager or 41 | * AuthenticationProvider implementations that are satisfied with 42 | * producing a trusted (i.e. {@link #isAuthenticated()} = true) 43 | * authentication token. 44 | * 45 | * @param principal 46 | * @param authorities 47 | */ 48 | public SmsCodeAuthenticationToken(Object principal, 49 | Collection authorities) { 50 | super(authorities); 51 | this.principal = principal; 52 | super.setAuthenticated(true); // must use super, as we override 53 | } 54 | 55 | // ~ Methods 56 | // ======================================================================================================== 57 | 58 | public Object getCredentials() { 59 | return null; 60 | } 61 | 62 | public Object getPrincipal() { 63 | return this.principal; 64 | } 65 | 66 | public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { 67 | if (isAuthenticated) { 68 | throw new IllegalArgumentException( 69 | "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); 70 | } 71 | 72 | super.setAuthenticated(false); 73 | } 74 | 75 | @Override 76 | public void eraseCredentials() { 77 | super.eraseCredentials(); 78 | } 79 | } -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/authentication/sms/SmsCodeCheckFilter.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.authentication.sms; 2 | 3 | import club.yuit.oauth.boot.exception.VerificationCodeFailureException; 4 | import club.yuit.oauth.boot.support.BootSecurityProperties; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.apache.commons.lang3.StringUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.data.redis.core.StringRedisTemplate; 12 | import org.springframework.security.core.AuthenticationException; 13 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 14 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 15 | import org.springframework.util.AntPathMatcher; 16 | import org.springframework.util.PathMatcher; 17 | import org.springframework.web.filter.OncePerRequestFilter; 18 | 19 | import javax.servlet.FilterChain; 20 | import javax.servlet.ServletException; 21 | import javax.servlet.http.HttpServletRequest; 22 | import javax.servlet.http.HttpServletResponse; 23 | import java.io.IOException; 24 | 25 | /** 26 | * @author yuit 27 | * @date 2018/10/19 15:33 28 | */ 29 | @Getter 30 | @Setter 31 | @Slf4j 32 | public class SmsCodeCheckFilter extends OncePerRequestFilter { 33 | 34 | 35 | private AuthenticationFailureHandler failureHandler; 36 | private BootSecurityProperties properties; 37 | private StringRedisTemplate template; 38 | private AuthenticationSuccessHandler successHandler; 39 | private PathMatcher pathMatcher; 40 | 41 | 42 | 43 | public SmsCodeCheckFilter(BootSecurityProperties properties) { 44 | setProperties(properties); 45 | this.pathMatcher = new AntPathMatcher(); 46 | 47 | } 48 | 49 | @Override 50 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 51 | 52 | if(this.pathMatcher.match("/authentication/mobile",request.getRequestURI()) 53 | && StringUtils.equalsAnyIgnoreCase(request.getMethod(),"post")){ 54 | try { 55 | check(request,response,filterChain); 56 | }catch (Exception ex){ 57 | if (ex instanceof VerificationCodeFailureException){ 58 | failureHandler.onAuthenticationFailure(request,response, (AuthenticationException) ex); 59 | } 60 | throw ex; 61 | } 62 | 63 | }else { 64 | filterChain.doFilter(request,response); 65 | } 66 | } 67 | 68 | private void check(HttpServletRequest request, HttpServletResponse response,FilterChain chain) throws VerificationCodeFailureException, IOException, ServletException { 69 | 70 | String mobile = request.getParameter(properties.getSmsLogin().getMobileParameterName()); 71 | String code = request.getParameter(properties.getSmsLogin().getCodeParameterName()); 72 | if (mobile.trim().length()==0) { 73 | throw new VerificationCodeFailureException("手机号不能为空"); 74 | } 75 | 76 | if (!this.template.hasKey(mobile)) { 77 | throw new VerificationCodeFailureException("验证码过期或手机号错误"); 78 | } 79 | 80 | Long expireTime= this.template.getExpire(mobile); 81 | 82 | if (expireTime<=0){ 83 | throw new VerificationCodeFailureException("验证码过期"); 84 | } 85 | 86 | String redisCode = this.template.opsForValue().get(mobile); 87 | 88 | if (!code.equals(redisCode)) { 89 | throw new VerificationCodeFailureException("验证码错误"); 90 | } 91 | 92 | chain.doFilter(request,response); 93 | } 94 | 95 | 96 | 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/authentication/sms/SmsSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.authentication.sms; 2 | 3 | import club.yuit.oauth.boot.handler.BootLoginFailureHandler; 4 | import club.yuit.oauth.boot.support.BootSecurityProperties; 5 | import club.yuit.oauth.boot.support.BootSmsUserDetailService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.data.redis.core.StringRedisTemplate; 9 | import org.springframework.security.authentication.AuthenticationManager; 10 | import org.springframework.security.config.annotation.SecurityConfigurerAdapter; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.web.DefaultSecurityFilterChain; 13 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 14 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 15 | 16 | /** 17 | * @author yuit 18 | * @date 2019/11/26 9:27 19 | **/ 20 | @Configuration 21 | public class SmsSecurityConfig extends SecurityConfigurerAdapter { 22 | 23 | private SmsAuthenticationProvider authenticationProvider; 24 | private SmsCodeAuthenticationFilter authenticationFilter; 25 | private SmsCodeCheckFilter codeCheckFilter; 26 | 27 | 28 | public SmsSecurityConfig(BootSmsUserDetailService userDetailsService, 29 | StringRedisTemplate redisTemplate, 30 | @Autowired(required = false) 31 | BootLoginFailureHandler failureHandler, 32 | @Autowired(required = false) 33 | AuthenticationSuccessHandler successHandler, 34 | BootSecurityProperties properties) { 35 | 36 | 37 | this.authenticationFilter = new SmsCodeAuthenticationFilter(properties.getSmsLogin().getLoginProcessUrl()); 38 | this.authenticationFilter.setAuthenticationFailureHandler(failureHandler); 39 | if (successHandler!=null) { 40 | this.authenticationFilter.setAuthenticationSuccessHandler(successHandler); 41 | } 42 | 43 | this.authenticationProvider = new SmsAuthenticationProvider(); 44 | this.authenticationProvider.setUserDetailsService(userDetailsService); 45 | 46 | this.codeCheckFilter = new SmsCodeCheckFilter(properties); 47 | this.codeCheckFilter.setFailureHandler(failureHandler); 48 | this.codeCheckFilter.setTemplate(redisTemplate); 49 | this.codeCheckFilter.setSuccessHandler(successHandler); 50 | 51 | 52 | } 53 | 54 | @Override 55 | public void configure(HttpSecurity http) throws Exception { 56 | this.authenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class)); 57 | http.authenticationProvider(this.authenticationProvider) 58 | .addFilterBefore(this.codeCheckFilter,UsernamePasswordAuthenticationFilter.class) 59 | .addFilterAfter(this.authenticationFilter, UsernamePasswordAuthenticationFilter.class); 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/config/CoreConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.config; 2 | 3 | import club.yuit.oauth.boot.support.BootSecurityProperties; 4 | import club.yuit.oauth.boot.support.code.BootCodeService; 5 | import club.yuit.oauth.boot.support.code.RedisCodeService; 6 | import club.yuit.oauth.boot.support.code.SessionCodeService; 7 | import club.yuit.oauth.boot.support.properities.BootBaseLoginProperties; 8 | import club.yuit.oauth.boot.support.properities.CodeStoreType; 9 | import org.mybatis.spring.annotation.MapperScan; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.data.redis.core.StringRedisTemplate; 13 | import org.springframework.security.authentication.AuthenticationManager; 14 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 15 | import org.springframework.security.crypto.password.PasswordEncoder; 16 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 17 | import org.springframework.web.servlet.config.annotation.ViewResolverRegistry; 18 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; 19 | import org.springframework.web.servlet.view.InternalResourceViewResolver; 20 | import springfox.documentation.builders.ApiInfoBuilder; 21 | import springfox.documentation.builders.ParameterBuilder; 22 | import springfox.documentation.builders.PathSelectors; 23 | import springfox.documentation.builders.RequestHandlerSelectors; 24 | import springfox.documentation.schema.ModelRef; 25 | import springfox.documentation.service.ApiInfo; 26 | import springfox.documentation.service.Contact; 27 | import springfox.documentation.service.Parameter; 28 | import springfox.documentation.spi.DocumentationType; 29 | import springfox.documentation.spring.web.plugins.Docket; 30 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 31 | 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | /** 36 | * @author yuit 37 | * @date 2018/10/9 15:08 38 | **/ 39 | @Configuration 40 | @EnableSwagger2 41 | public class CoreConfig extends WebMvcConfigurationSupport { 42 | 43 | 44 | 45 | @Override 46 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 47 | registry.addResourceHandler("/swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/"); 48 | registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); 49 | registry.addResourceHandler("/statics/**") 50 | .addResourceLocations("classpath:/statics/"); 51 | 52 | registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/statics/favicon.ico"); 53 | } 54 | 55 | /** 56 | * Could not resolve view with name 'forward:/oauth/confirm_access' in servlet with name 'dispatcherServlet' 57 | * 58 | */ 59 | /*@Override 60 | protected void configureViewResolvers(ViewResolverRegistry registry) { 61 | registry.viewResolver(new InternalResourceViewResolver()); 62 | }*/ 63 | 64 | @Bean 65 | public Docket docket() { 66 | 67 | ParameterBuilder builder = new ParameterBuilder(); 68 | List parameters = new ArrayList<>(); 69 | 70 | builder.name("Authorization").description("token").modelRef(new ModelRef("string")) 71 | .parameterType("header") 72 | .required(false) 73 | .build(); 74 | parameters.add(builder.build()); 75 | 76 | return new Docket(DocumentationType.SWAGGER_2) 77 | .globalOperationParameters(parameters) 78 | .apiInfo(this.apiInfo()) 79 | .select() 80 | .apis(RequestHandlerSelectors.basePackage("club.yuit.oauth.boot.controller")) 81 | .paths(PathSelectors.any()) 82 | .build(); 83 | } 84 | 85 | private ApiInfo apiInfo() { 86 | return new ApiInfoBuilder() 87 | .title("Boot API") 88 | .description("创建于 2018-10-12") 89 | .contact(new Contact("yuit", "", "1239964852g@gmail.com")) 90 | .version("1.0") 91 | .build(); 92 | } 93 | 94 | 95 | @Bean 96 | public BootCodeService codeService(StringRedisTemplate template, BootSecurityProperties properties){ 97 | if (properties.getCodeStoreType() == CodeStoreType.redis) { 98 | return new RedisCodeService(template,properties.getCodeExpireTime()); 99 | }else { 100 | return new SessionCodeService(); 101 | } 102 | } 103 | 104 | 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/config/DbConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.config; 2 | 3 | import com.alibaba.druid.pool.DruidDataSource; 4 | import lombok.Data; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Primary; 11 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 12 | 13 | import javax.sql.DataSource; 14 | 15 | /** 16 | * @author yuit 17 | * @date time 2018/10/9 15:14 18 | * 数据库配置 19 | **/ 20 | @Configuration 21 | @ConfigurationProperties(prefix = "spring.datasource") 22 | @Data 23 | public class DbConfig { 24 | 25 | private String username; 26 | private String url; 27 | private String password; 28 | private String driverClassName; 29 | 30 | private Logger logger = LoggerFactory.getLogger(getClass()); 31 | 32 | 33 | /** 34 | * 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 52 | * 53 | * */ 54 | @Bean 55 | @Primary 56 | public DataSource dataSource() { 57 | DruidDataSource dr = new DruidDataSource(); 58 | dr.setUsername(this.username); 59 | dr.setPassword(this.password); 60 | dr.setDriverClassName(this.driverClassName); 61 | dr.setUrl(this.url); 62 | 63 | this.logger.info(this.url+":"+this.username+":"+this.password); 64 | 65 | dr.setInitialSize(10); 66 | dr.setMinIdle(30); 67 | dr.setMaxActive(300); 68 | dr.setMaxWait(3600000); 69 | dr.setTimeBetweenEvictionRunsMillis(60000); 70 | dr.setMinEvictableIdleTimeMillis(30000); 71 | dr.setValidationQuery("select 'X' from dual"); 72 | dr.setTestWhileIdle(true); 73 | dr.setTestOnBorrow(false); 74 | dr.setTestOnReturn(false); 75 | dr.setPoolPreparedStatements(true); 76 | dr.setMaxPoolPreparedStatementPerConnectionSize(20); 77 | 78 | return dr; 79 | } 80 | 81 | @Bean 82 | public DataSourceTransactionManager transactionManager(){ 83 | return new DataSourceTransactionManager(dataSource()); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/config/RedisConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 4 | import com.fasterxml.jackson.annotation.PropertyAccessor; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.springframework.cache.CacheManager; 7 | import org.springframework.cache.annotation.EnableCaching; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import org.springframework.context.annotation.Primary; 11 | import org.springframework.data.redis.cache.RedisCacheManager; 12 | import org.springframework.data.redis.connection.RedisConnectionFactory; 13 | import org.springframework.data.redis.core.RedisTemplate; 14 | import org.springframework.data.redis.core.StringRedisTemplate; 15 | import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; 16 | import org.springframework.data.redis.serializer.StringRedisSerializer; 17 | 18 | import javax.crypto.KeyGenerator; 19 | import java.lang.reflect.Method; 20 | 21 | /** 22 | * @author yuit 23 | * @date 2018/10/10 11:08 24 | * 25 | **/ 26 | @Configuration 27 | @EnableCaching 28 | public class RedisConfig { 29 | 30 | 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.config; 2 | 3 | import club.yuit.oauth.boot.authentication.sms.SmsAuthenticationProvider; 4 | import club.yuit.oauth.boot.authentication.sms.SmsSecurityConfig; 5 | import club.yuit.oauth.boot.filter.BootPictureCodeAuthenticationFilter; 6 | import club.yuit.oauth.boot.handler.BootLoginFailureHandler; 7 | import club.yuit.oauth.boot.support.BootSecurityProperties; 8 | import club.yuit.oauth.boot.support.BootUserDetailService; 9 | import club.yuit.oauth.boot.support.code.BootCodeService; 10 | import club.yuit.oauth.boot.support.properities.BootBaseLoginProperties; 11 | import club.yuit.oauth.boot.support.properities.BootSmsLoginProperties; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.core.annotation.Order; 15 | import org.springframework.security.authentication.AuthenticationManager; 16 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 17 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 18 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 19 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 20 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 21 | import org.springframework.security.crypto.password.PasswordEncoder; 22 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 23 | 24 | /** 25 | * @author yuit 26 | * @date 2018/10/10 11:48 27 | **/ 28 | @Configuration 29 | @Order(1) 30 | public class SecurityConfig extends WebSecurityConfigurerAdapter { 31 | 32 | 33 | private BootUserDetailService userDetailService; 34 | private BootSecurityProperties properties; 35 | private BootLoginFailureHandler handler; 36 | private SmsSecurityConfig smsSecurityConfig; 37 | private BootPictureCodeAuthenticationFilter pictureCodeAuthenticationFilter; 38 | 39 | 40 | public SecurityConfig(BootUserDetailService userDetailService, 41 | BootSecurityProperties properties, 42 | BootLoginFailureHandler handler, 43 | SmsSecurityConfig smsSecurityConfig, 44 | BootCodeService codeService) { 45 | this.userDetailService = userDetailService; 46 | this.properties = properties; 47 | this.handler = handler; 48 | this.smsSecurityConfig = smsSecurityConfig; 49 | pictureCodeAuthenticationFilter = new BootPictureCodeAuthenticationFilter(properties,codeService, handler); 50 | } 51 | 52 | /** 53 | * 让Security 忽略这些url,不做拦截处理 54 | * 55 | * @param 56 | * @throws Exception 57 | */ 58 | @Override 59 | public void configure(WebSecurity web) throws Exception { 60 | web.ignoring().antMatchers 61 | ("/swagger-ui.html/**", "/webjars/**", 62 | "/swagger-resources/**", "/v2/api-docs/**", 63 | "/swagger-resources/configuration/ui/**","/statics/**",properties.getCodePath(), "/swagger-resources/configuration/security/**", 64 | "/images/**"); 65 | } 66 | 67 | @Override 68 | public void configure(AuthenticationManagerBuilder auth) throws Exception { 69 | auth.userDetailsService(userDetailService); 70 | } 71 | 72 | @Override 73 | protected void configure(HttpSecurity http) throws Exception { 74 | 75 | BootBaseLoginProperties base = properties.getBaseLogin(); 76 | BootSmsLoginProperties sms = properties.getSmsLogin(); 77 | http 78 | // http security 要拦截的url,这里这拦截,oauth2相关和登录登录相关的url,其他的交给资源服务处理 79 | .requestMatchers() 80 | .antMatchers( "/oauth/**",properties.getLoginPage(), 81 | base.getLoginProcessUrl(),sms.getLoginProcessUrl()) 82 | .and() 83 | .authorizeRequests() 84 | // 自定义页面或处理url是,如果不配置全局允许,浏览器会提示服务器将页面转发多次 85 | .antMatchers(properties.getLoginPage(),base.getLoginProcessUrl(),sms.getLoginProcessUrl()) 86 | .permitAll() 87 | .anyRequest() 88 | .authenticated(); 89 | 90 | // 表单登录 91 | http.formLogin() 92 | .failureHandler(handler) 93 | // 请求 {用户名} 参数名称 94 | .usernameParameter(base.getUsernameParameterName()) 95 | // 请求 {密码} 参数名 96 | .passwordParameter(base.getPasswordParameterName()) 97 | // 登录页面 98 | .loginPage(properties.getLoginPage()) 99 | // 登录处理url 100 | .loginProcessingUrl(base.getLoginProcessUrl()); 101 | 102 | http.httpBasic().disable(); 103 | 104 | http.apply(this.smsSecurityConfig); 105 | 106 | // 用户密码验证之前校验验证码 107 | http.addFilterBefore(pictureCodeAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); 108 | 109 | } 110 | 111 | 112 | @Override 113 | @Bean 114 | public AuthenticationManager authenticationManagerBean() throws Exception { 115 | return super.authenticationManagerBean(); 116 | } 117 | 118 | @Bean 119 | public PasswordEncoder passwordEncoder() { 120 | return new BCryptPasswordEncoder(); 121 | } 122 | 123 | 124 | @Bean 125 | public SmsAuthenticationProvider smsAuthenticationProvider (){ 126 | return new SmsAuthenticationProvider(); 127 | } 128 | 129 | 130 | 131 | 132 | 133 | 134 | } 135 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/config/auth2/OAuth2AuthorizationServerConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.config.auth2; 2 | 3 | import club.yuit.oauth.boot.filter.BootBasicAuthenticationFilter; 4 | import club.yuit.oauth.boot.support.BootUserDetailService; 5 | import club.yuit.oauth.boot.support.oauth2.BootClientDetailsService; 6 | import club.yuit.oauth.boot.support.oauth2.BootOAuth2WebResponseExceptionTranslator; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.http.HttpMethod; 10 | import org.springframework.security.authentication.AuthenticationManager; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 14 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 15 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 16 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 17 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 18 | import org.springframework.security.oauth2.provider.token.TokenStore; 19 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 20 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; 21 | import org.springframework.security.web.AuthenticationEntryPoint; 22 | 23 | /** 24 | * @author yuit 25 | * @date 2018/10/15 14:52 26 | **/ 27 | @Configuration 28 | @EnableAuthorizationServer 29 | public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { 30 | 31 | 32 | private AuthenticationManager authenticationManager; 33 | private BootClientDetailsService clientDetailsService; 34 | private TokenStore tokenStore; 35 | private JwtAccessTokenConverter converter; 36 | private AuthenticationEntryPoint authenticationEntryPoint; 37 | private BootOAuth2WebResponseExceptionTranslator bootWebResponseExceptionTranslator; 38 | private PasswordEncoder passwordEncoder; 39 | private UserDetailsService userDetailsService; 40 | 41 | @Autowired(required = false) 42 | public OAuth2AuthorizationServerConfig(AuthenticationManager authenticationManager, 43 | BootClientDetailsService clientDetailsService, 44 | TokenStore tokenStore, JwtAccessTokenConverter converter, 45 | AuthenticationEntryPoint authenticationEntryPoint, 46 | BootOAuth2WebResponseExceptionTranslator bootWebResponseExceptionTranslator, 47 | PasswordEncoder passwordEncoder, BootUserDetailService userDetailsService) { 48 | this.authenticationManager = authenticationManager; 49 | this.clientDetailsService = clientDetailsService; 50 | this.tokenStore = tokenStore; 51 | this.converter = converter; 52 | this.authenticationEntryPoint = authenticationEntryPoint; 53 | this.bootWebResponseExceptionTranslator = bootWebResponseExceptionTranslator; 54 | this.passwordEncoder = passwordEncoder; 55 | this.userDetailsService = userDetailsService; 56 | } 57 | 58 | public OAuth2AuthorizationServerConfig() { 59 | super(); 60 | } 61 | 62 | @Override 63 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 64 | 65 | 66 | // 允许表单登录 67 | security.allowFormAuthenticationForClients(); 68 | 69 | 70 | 71 | // 自定义异常处理端口 72 | security.authenticationEntryPoint(authenticationEntryPoint); 73 | 74 | // 客户端认证之前的过滤器 75 | BootBasicAuthenticationFilter filter = new BootBasicAuthenticationFilter(this.clientDetailsService,this.passwordEncoder); 76 | security.addTokenEndpointAuthenticationFilter(filter); 77 | 78 | security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); 79 | 80 | } 81 | 82 | @Override 83 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 84 | // 配置加载客户端的service 85 | clients.withClientDetails(clientDetailsService); 86 | } 87 | 88 | @Override 89 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 90 | 91 | endpoints 92 | // token 存储方式 93 | .tokenStore(tokenStore) 94 | .authenticationManager(authenticationManager) 95 | // 不配置会导致token无法刷新 96 | .userDetailsService(userDetailsService) 97 | .allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET); 98 | 99 | // 判断当前是否使用jwt 100 | if(!(tokenStore instanceof RedisTokenStore) && this.converter!=null){ 101 | endpoints.accessTokenConverter(converter); 102 | } 103 | 104 | 105 | // 处理 ExceptionTranslationFilter 抛出的异常 106 | endpoints.exceptionTranslator(bootWebResponseExceptionTranslator); 107 | 108 | endpoints.pathMapping("/oauth/confirm_access","/custom/confirm_access"); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/config/auth2/OAuth2ResourceServerConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.config.auth2; 2 | 3 | import club.yuit.oauth.boot.support.BootSecurityProperties; 4 | import club.yuit.oauth.boot.support.oauth2.BootAccessDeniedHandler; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 8 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 9 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; 10 | import org.springframework.security.oauth2.provider.token.TokenStore; 11 | import org.springframework.security.web.AuthenticationEntryPoint; 12 | 13 | 14 | /** 15 | * @author yuit 16 | * @date 2018/10/15 14:57 17 | * 资源服务配置 18 | **/ 19 | @Configuration 20 | @EnableResourceServer 21 | public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter{ 22 | 23 | private AuthenticationEntryPoint point; 24 | private BootAccessDeniedHandler handler; 25 | private TokenStore tokenStore; 26 | private BootSecurityProperties properties; 27 | 28 | public OAuth2ResourceServerConfig(AuthenticationEntryPoint point, BootAccessDeniedHandler handler, TokenStore tokenStore, BootSecurityProperties properties) { 29 | this.point = point; 30 | this.handler = handler; 31 | this.tokenStore = tokenStore; 32 | this.properties = properties; 33 | } 34 | 35 | @Override 36 | public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 37 | 38 | resources.tokenStore(tokenStore) 39 | .resourceId("boot-server"); 40 | 41 | resources.authenticationEntryPoint(point).accessDeniedHandler(handler); 42 | 43 | } 44 | 45 | @Override 46 | public void configure(HttpSecurity http) throws Exception { 47 | 48 | http 49 | // Allows restricting access based upon the {@link HttpServletRequest} using 50 | .authorizeRequests() 51 | .antMatchers("/favicon.ico","/oauth/**", 52 | properties.getBaseLogin().getLoginProcessUrl(), 53 | properties.getLoginPage(), 54 | properties.getSmsLogin().getLoginProcessUrl()) 55 | .permitAll() 56 | .anyRequest() 57 | .access("#oauth2.hasAnyScope('all','select')"); 58 | } 59 | 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/config/auth2/TokenStoreConfig.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.config.auth2; 2 | 3 | import club.yuit.oauth.boot.support.BootSecurityProperties; 4 | import org.springframework.beans.factory.BeanCreationException; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.context.annotation.Primary; 10 | import org.springframework.data.redis.connection.RedisConnectionFactory; 11 | import org.springframework.security.oauth2.provider.token.AccessTokenConverter; 12 | import org.springframework.security.oauth2.provider.token.TokenStore; 13 | import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; 14 | import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; 15 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 16 | import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; 17 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; 18 | 19 | import javax.sql.DataSource; 20 | 21 | /** 22 | * @author yuit 23 | * @date 2018/10/17 16:38 24 | * 25 | * token 存储方式配置 26 | * 27 | **/ 28 | @Configuration 29 | public class TokenStoreConfig { 30 | 31 | private BootSecurityProperties properties; 32 | 33 | private RedisConnectionFactory factory; 34 | 35 | 36 | 37 | private DataSource dataSource; 38 | 39 | @Autowired(required = false) 40 | public TokenStoreConfig(BootSecurityProperties properties, RedisConnectionFactory factory, DataSource dataSource) { 41 | this.properties = properties; 42 | this.factory = factory; 43 | 44 | this.dataSource = dataSource; 45 | } 46 | 47 | @Bean 48 | public TokenStore tokenStore() throws Exception { 49 | 50 | TokenStore store = null; 51 | 52 | switch (properties.getOauth2().getTokenStoreType()) { 53 | case jwt: 54 | store = new JwtTokenStore(jwtAccessTokenConverter()); 55 | break; 56 | case redis: 57 | if (factory == null) { 58 | throw new BeanCreationException("配置Redis存储Token需要redisConnectionFactory bean,未找到"); 59 | } 60 | store = new RedisTokenStore(factory); 61 | break; 62 | case jdbc: 63 | 64 | if(dataSource==null){ 65 | throw new BeanCreationException("配置jdbc存储Token需要dataSource bean,未找到"); 66 | } 67 | store=new JdbcTokenStore(dataSource); 68 | break; 69 | default: 70 | store = new InMemoryTokenStore(); 71 | } 72 | 73 | return store; 74 | } 75 | 76 | @Bean 77 | @Primary 78 | public JwtAccessTokenConverter jwtAccessTokenConverter() { 79 | JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 80 | converter.setSigningKey(properties.getOauth2().getTokenSigningKey()); 81 | return converter; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/controller/BaseMainController.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.controller; 2 | 3 | import club.yuit.oauth.boot.response.HttpResponse; 4 | import club.yuit.oauth.boot.response.SimpleResponse; 5 | import club.yuit.oauth.boot.support.BootSecurityProperties; 6 | import club.yuit.oauth.boot.support.DefaultBeanName; 7 | import club.yuit.oauth.boot.support.code.BootCodeService; 8 | import club.yuit.oauth.boot.support.code.VerificationCode; 9 | import club.yuit.oauth.boot.support.code.VerificationCodeGenerator; 10 | import club.yuit.oauth.boot.support.code.picture.DefaultPictureCodeGenerator; 11 | import club.yuit.oauth.boot.support.code.sms.DefaultSmsCodeGenerator; 12 | import club.yuit.oauth.boot.support.properities.BootBaseLoginProperties; 13 | import club.yuit.oauth.boot.support.properities.CodeStoreType; 14 | import club.yuit.oauth.boot.utils.HttpUtils; 15 | import lombok.extern.slf4j.Slf4j; 16 | import org.bouncycastle.util.encoders.Base64; 17 | import org.springframework.beans.factory.annotation.Qualifier; 18 | import org.springframework.http.MediaType; 19 | import org.springframework.stereotype.Controller; 20 | import org.springframework.ui.Model; 21 | import org.springframework.web.bind.annotation.GetMapping; 22 | import org.springframework.web.bind.annotation.RequestMapping; 23 | import org.springframework.web.bind.annotation.RequestParam; 24 | import org.springframework.web.bind.annotation.ResponseBody; 25 | 26 | import javax.imageio.ImageIO; 27 | import javax.servlet.http.HttpServletRequest; 28 | import javax.servlet.http.HttpServletResponse; 29 | import java.awt.*; 30 | import java.awt.image.BufferedImage; 31 | import java.io.ByteArrayOutputStream; 32 | import java.io.IOException; 33 | import java.io.OutputStream; 34 | import java.io.PrintWriter; 35 | import java.util.HashMap; 36 | import java.util.Map; 37 | import java.util.UUID; 38 | 39 | /** 40 | * @author yuit 41 | * @date 2018/10/9 15:09 42 | **/ 43 | @Controller 44 | @Slf4j 45 | public class BaseMainController { 46 | 47 | 48 | private BootSecurityProperties properties; 49 | 50 | 51 | public BaseMainController(BootSecurityProperties properties) { 52 | this.properties = properties; 53 | } 54 | 55 | @RequestMapping("${boot.oauth.login-page:/auth/login}") 56 | public String loginPage(Model model, HttpServletRequest request) { 57 | BootBaseLoginProperties base = properties.getBaseLogin(); 58 | String type = request.getParameter("type"); 59 | 60 | model.addAttribute("username", request.getParameter(base.getUsernameParameterName())); 61 | model.addAttribute("password", request.getParameter(base.getPasswordParameterName())); 62 | model.addAttribute("error", request.getAttribute("error")); 63 | if (type != null 64 | && (type.equalsIgnoreCase("base") 65 | || type.equalsIgnoreCase("sms") 66 | || type.equalsIgnoreCase("social"))) { 67 | model.addAttribute("type", type); 68 | } else { 69 | model.addAttribute("type", "base"); 70 | } 71 | 72 | model.addAttribute("sms", properties.getSmsLogin()); 73 | model.addAttribute("base", properties.getBaseLogin()); 74 | model.addAttribute("codePath", properties.getCodePath()); 75 | return "base-login"; 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/controller/BootGrantController.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.controller; 2 | 3 | import club.yuit.oauth.boot.entity.Client; 4 | import club.yuit.oauth.boot.service.IClientService; 5 | import club.yuit.oauth.boot.support.BootSecurityProperties; 6 | import org.springframework.security.oauth2.provider.AuthorizationRequest; 7 | import org.springframework.stereotype.Controller; 8 | import org.springframework.ui.Model; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.SessionAttributes; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author yuit 17 | * @date 2018/11/1 11:44 18 | * 19 | */ 20 | @Controller 21 | @SessionAttributes("authorizationRequest") 22 | public class BootGrantController { 23 | 24 | private BootSecurityProperties properties; 25 | private IClientService clientService; 26 | 27 | public BootGrantController(BootSecurityProperties properties, IClientService clientService) { 28 | this.properties = properties; 29 | this.clientService = clientService; 30 | } 31 | 32 | @RequestMapping("/custom/confirm_access") 33 | public String getAccessConfirmation(Map param, HttpServletRequest request, Model model) throws Exception { 34 | 35 | AuthorizationRequest authorizationRequest = (AuthorizationRequest) param.get("authorizationRequest"); 36 | if (authorizationRequest==null){ 37 | return "redirect:"+properties.getLoginPage(); 38 | } 39 | String clientId = authorizationRequest.getClientId(); 40 | model.addAttribute("scopes",authorizationRequest.getScope()); 41 | Client client = this.clientService.findClientByClientId(clientId); 42 | model.addAttribute("client",client); 43 | 44 | return "base-grant"; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/controller/ClientController.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.controller; 2 | 3 | import club.yuit.oauth.boot.entity.Client; 4 | import club.yuit.oauth.boot.response.BaseResponse; 5 | import club.yuit.oauth.boot.response.HttpResponse; 6 | import club.yuit.oauth.boot.service.IClientService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.crypto.password.PasswordEncoder; 9 | import org.springframework.web.bind.annotation.PostMapping; 10 | import org.springframework.web.bind.annotation.RequestBody; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.validation.Valid; 15 | 16 | /** 17 | * @author yuit 18 | * @date 2018/10/16 10:32 19 | * 20 | **/ 21 | @RestController 22 | @RequestMapping("client") 23 | public class ClientController { 24 | 25 | @Autowired 26 | private IClientService clientService; 27 | 28 | @Autowired 29 | private PasswordEncoder passwordEncoder; 30 | 31 | @PostMapping("/register") 32 | public BaseResponse clientRegistered(@RequestBody @Valid Client client) { 33 | 34 | client.setClientSecret(passwordEncoder.encode(client.getClientSecret())); 35 | boolean i = clientService.save(client); 36 | return HttpResponse.baseResponse(200); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/controller/CodeController.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.controller; 2 | 3 | import club.yuit.oauth.boot.response.HttpResponse; 4 | import club.yuit.oauth.boot.response.SimpleResponse; 5 | import club.yuit.oauth.boot.support.BootSecurityProperties; 6 | import club.yuit.oauth.boot.support.DefaultBeanName; 7 | import club.yuit.oauth.boot.support.code.BootCodeService; 8 | import club.yuit.oauth.boot.support.code.VerificationCode; 9 | import club.yuit.oauth.boot.support.code.VerificationCodeGenerator; 10 | import club.yuit.oauth.boot.support.code.picture.DefaultPictureCodeGenerator; 11 | import club.yuit.oauth.boot.support.code.sms.DefaultSmsCodeGenerator; 12 | import club.yuit.oauth.boot.support.properities.CodeStoreType; 13 | import club.yuit.oauth.boot.utils.HttpUtils; 14 | import jdk.nashorn.internal.objects.annotations.Getter; 15 | import org.bouncycastle.util.encoders.Base64; 16 | import org.springframework.http.MediaType; 17 | import org.springframework.stereotype.Controller; 18 | import org.springframework.ui.Model; 19 | import org.springframework.web.bind.annotation.GetMapping; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RequestParam; 22 | import org.springframework.web.bind.annotation.ResponseBody; 23 | 24 | import javax.imageio.ImageIO; 25 | import javax.servlet.http.Cookie; 26 | import javax.servlet.http.HttpServletRequest; 27 | import javax.servlet.http.HttpServletResponse; 28 | import java.awt.image.BufferedImage; 29 | import java.io.ByteArrayOutputStream; 30 | import java.io.OutputStream; 31 | import java.util.HashMap; 32 | import java.util.Map; 33 | import java.util.UUID; 34 | 35 | /** 36 | * @author yuit 37 | * @date 2019/11/27 9:27 38 | **/ 39 | @Controller 40 | @RequestMapping("${boot.oauth.code-path:/auth/code}") 41 | public class CodeController { 42 | 43 | 44 | private BootSecurityProperties properties; 45 | private Map codeGenerators; 46 | 47 | public CodeController(BootSecurityProperties properties, Map codeGenerators) { 48 | this.properties = properties; 49 | this.codeGenerators = codeGenerators; 50 | } 51 | 52 | /** 53 | * 54 | * @param request request 55 | * @param type sms/picture 56 | * @throws Exception ex 57 | */ 58 | @RequestMapping() 59 | @ResponseBody 60 | public SimpleResponse> codeGenerateJson(HttpServletRequest request, @RequestParam("type") String type) throws Exception { 61 | 62 | String tmp = type.trim(); 63 | Map responseBoy= new HashMap<>(); 64 | 65 | if (tmp.equals("picture")) { 66 | 67 | String key = this.properties.getBaseLogin().getPictureCodeParameterName(); 68 | 69 | if (this.properties.getCodeStoreType()== CodeStoreType.redis){ 70 | key = UUID.randomUUID().toString(); 71 | } 72 | 73 | VerificationCode pCode = ((DefaultPictureCodeGenerator)this.codeGenerators.get(DefaultBeanName.DEFAULT_PICTURE_CODE_GENERATOR_BEAN)) 74 | .generator(key); 75 | 76 | ByteArrayOutputStream out= new ByteArrayOutputStream(); 77 | 78 | ImageIO.write(pCode.getContent(),"png",out); 79 | 80 | byte[] bts = out.toByteArray(); 81 | 82 | String base64_code = Base64.toBase64String(bts); 83 | // 删除 \n \r 84 | base64_code = base64_code.replaceAll("\n","").replace("\r",""); 85 | 86 | responseBoy.put("value","data:image/png;base64,"+base64_code); 87 | responseBoy.put("key",key); 88 | } else if (tmp.equals("sms")) { 89 | 90 | String key = request.getParameter("mobile"); 91 | 92 | VerificationCode sCode = ((DefaultSmsCodeGenerator)this.codeGenerators.get(DefaultBeanName.DEFAULT_SMS_CODE_GENERATOR_BEAN)) 93 | .generator(key); 94 | responseBoy.put("value",sCode.getContent()); 95 | responseBoy.put("key",key); 96 | responseBoy.put("expire",sCode.getExpirationTime()); 97 | } 98 | 99 | return HttpResponse.successSimpleResponse(responseBoy); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.controller; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.RestController; 5 | 6 | /** 7 | * @author yuit 8 | * @date 2018/11/1 16:44 9 | * 10 | */ 11 | @RestController 12 | public class TestController { 13 | 14 | @GetMapping("/other") 15 | public String test(){ 16 | return "other"; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/entity/Client.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | 8 | import javax.validation.constraints.NotNull; 9 | 10 | /** 11 | * @author yuit 12 | * @date 2018/10/16 9:23 13 | * 14 | **/ 15 | @Data 16 | @TableName("clients") 17 | public class Client { 18 | @TableId 19 | private String id; 20 | 21 | private String name; 22 | 23 | @TableField("clientId") 24 | @NotNull 25 | private String clientId; 26 | @TableField("resourceIds") 27 | private String resourceIds; 28 | @TableField("isSecretRequired") 29 | private Boolean isSecretRequired; 30 | @TableField("clientSecret") 31 | @NotNull 32 | private String clientSecret; 33 | @TableField("isScoped") 34 | private Boolean isScoped; 35 | @TableField("scope") 36 | private String scope; 37 | @TableField("authorizedGrantTypes") 38 | @NotNull 39 | private String authorizedGrantTypes; 40 | @TableField("registeredRedirectUri") 41 | @NotNull 42 | private String registeredRedirectUri; 43 | @TableField("authorities") 44 | private String authorities; 45 | @TableField("isAutoApprove") 46 | private Boolean isAutoApprove; 47 | @TableField("accessTokenValiditySeconds") 48 | @NotNull 49 | private Integer accessTokenValiditySeconds; 50 | @TableField("refreshTokenValiditySeconds") 51 | @NotNull 52 | private Integer refreshTokenValiditySeconds; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/entity/User.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | import org.springframework.security.core.GrantedAuthority; 8 | import org.springframework.security.core.userdetails.UserDetails; 9 | 10 | import java.util.Collection; 11 | import java.util.List; 12 | 13 | /** 14 | * @author yuit 15 | * @date 2018/10/9 15:43 16 | * 17 | **/ 18 | @Data 19 | @TableName("user") 20 | public class User implements UserDetails { 21 | @TableId 22 | private String id; 23 | private String username; 24 | private String email; 25 | @TableField("isEnable") 26 | private Boolean isEnable; 27 | @TableField("isExpired") 28 | private Boolean isExpired; 29 | @TableField("isLocked") 30 | private Boolean isLocked; 31 | private String password; 32 | private String gender; 33 | private String mobile; 34 | 35 | @TableField(exist = false) 36 | private List authorities; 37 | 38 | @Override 39 | public List getAuthorities() { 40 | return authorities; 41 | } 42 | 43 | @Override 44 | public boolean isAccountNonExpired() { 45 | return true; 46 | } 47 | 48 | @Override 49 | public boolean isAccountNonLocked() { 50 | return this.isLocked; 51 | } 52 | 53 | @Override 54 | public boolean isCredentialsNonExpired() { 55 | return true; 56 | } 57 | 58 | @Override 59 | public boolean isEnabled() { 60 | return this.isEnable; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/exception/ArgumentsFailureException.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.exception; 2 | 3 | /** 4 | * @author yuit 5 | * @date 2018/8/6 15:56 6 | * 参数不正确 7 | **/ 8 | public class ArgumentsFailureException extends RuntimeException { 9 | 10 | public ArgumentsFailureException() { 11 | this("参数错误"); 12 | } 13 | 14 | public ArgumentsFailureException(String message) { 15 | super(message); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/exception/AuthFailureException.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | /** 6 | * @author yuit 7 | * @date 2018/8/6 15:56 8 | * 认证失败 9 | **/ 10 | public class AuthFailureException extends AuthenticationException { 11 | 12 | public AuthFailureException() { 13 | this("认证失败!"); 14 | } 15 | 16 | public AuthFailureException(String message) { 17 | super(message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/exception/NotAuthException.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.exception; 2 | 3 | /** 4 | * @author yuit 5 | * @date Time 2018/8/6 15:56 6 | * 没有认证或是token过期 7 | **/ 8 | public class NotAuthException extends RuntimeException { 9 | 10 | public NotAuthException() { 11 | this("没有认证!"); 12 | } 13 | 14 | public NotAuthException(String message) { 15 | super(message); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/exception/NotAuthorityException.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.exception; 2 | 3 | /** 4 | * @author yuit 5 | * @date Time 2018/8/6 15:56 6 | * 没有权限 7 | **/ 8 | public class NotAuthorityException extends RuntimeException{ 9 | 10 | public NotAuthorityException() { 11 | this("没有权限!"); 12 | } 13 | 14 | public NotAuthorityException(String message) { 15 | super(message); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/exception/VerificationCodeFailureException.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.exception; 2 | 3 | 4 | import org.springframework.security.core.AuthenticationException; 5 | 6 | /** 7 | * @author yuit 8 | * @date 2018/10/19 16:18 9 | * 10 | */ 11 | public class VerificationCodeFailureException extends AuthenticationException { 12 | 13 | public VerificationCodeFailureException(String msg, Throwable t) { 14 | super(msg, t); 15 | } 16 | 17 | public VerificationCodeFailureException(String msg) { 18 | super(msg); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/filter/BootBasicAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.filter; 2 | 3 | import club.yuit.oauth.boot.response.BaseResponse; 4 | import club.yuit.oauth.boot.response.HttpResponse; 5 | import club.yuit.oauth.boot.support.oauth2.BootClientDetails; 6 | import club.yuit.oauth.boot.utils.HttpUtils; 7 | import org.springframework.http.HttpHeaders; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 10 | import org.springframework.security.core.Authentication; 11 | import org.springframework.security.core.context.SecurityContextHolder; 12 | import org.springframework.security.crypto.password.PasswordEncoder; 13 | import org.springframework.security.oauth2.provider.ClientDetailsService; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.web.filter.OncePerRequestFilter; 16 | 17 | import javax.servlet.FilterChain; 18 | import javax.servlet.ServletException; 19 | import javax.servlet.http.HttpServletRequest; 20 | import javax.servlet.http.HttpServletResponse; 21 | import java.io.IOException; 22 | import java.util.Base64; 23 | 24 | /** 25 | * @author yuit 26 | * @date 2018/11/5 11:38 27 | * 认证不带客户端信息参数处理 filter 28 | * 29 | */ 30 | public class BootBasicAuthenticationFilter extends OncePerRequestFilter { 31 | 32 | private ClientDetailsService clientDetailsService; 33 | private PasswordEncoder encoder; 34 | 35 | public BootBasicAuthenticationFilter(ClientDetailsService clientDetailsService, PasswordEncoder encoder) { 36 | this.clientDetailsService = clientDetailsService; 37 | this.encoder = encoder; 38 | } 39 | 40 | @Override 41 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 42 | 43 | 44 | if (!request.getRequestURI().equals("/oauth/token") || 45 | !request.getParameter("grant_type").equals("password")) { 46 | filterChain.doFilter(request, response); 47 | return; 48 | } 49 | 50 | String[] clientDetails = this.isHasClientDetails(request); 51 | 52 | if (clientDetails == null) { 53 | BaseResponse bs = HttpResponse.baseResponse(HttpStatus.UNAUTHORIZED.value(), "请求中未包含客户端信息"); 54 | HttpUtils.writer(bs, response); 55 | return; 56 | } 57 | 58 | this.handle(request,response,clientDetails,filterChain); 59 | 60 | 61 | } 62 | 63 | private void handle(HttpServletRequest request, HttpServletResponse response, String[] clientDetails,FilterChain filterChain) throws IOException, ServletException { 64 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 65 | 66 | if (authentication != null && authentication.isAuthenticated()) { 67 | filterChain.doFilter(request,response); 68 | return; 69 | } 70 | 71 | 72 | BootClientDetails details = (BootClientDetails) this.clientDetailsService.loadClientByClientId(clientDetails[0]); 73 | 74 | if (!this.encoder.matches(clientDetails[1],details.getClientSecret())){ 75 | BaseResponse bs = HttpResponse.baseResponse(HttpStatus.UNAUTHORIZED.value(), "client secret error!"); 76 | HttpUtils.writer(bs, response); 77 | return; 78 | } 79 | 80 | UsernamePasswordAuthenticationToken token = 81 | new UsernamePasswordAuthenticationToken(details.getClientId(), details.getClientSecret(), details.getAuthorities()); 82 | 83 | SecurityContextHolder.getContext().setAuthentication(token); 84 | 85 | 86 | filterChain.doFilter(request,response); 87 | } 88 | 89 | /** 90 | * 判断请求头中是否包含client信息,不包含返回null 91 | */ 92 | private String[] isHasClientDetails(HttpServletRequest request) { 93 | 94 | String[] params = null; 95 | 96 | String header = request.getHeader(HttpHeaders.AUTHORIZATION); 97 | 98 | if (header != null) { 99 | 100 | String basic = header.substring(0, 5); 101 | 102 | if (basic.toLowerCase().contains("basic")) { 103 | 104 | String tmp = header.substring(6); 105 | String defaultClientDetails = new String(Base64.getDecoder().decode(tmp)); 106 | 107 | String[] clientArrays = defaultClientDetails.split(":"); 108 | 109 | if (clientArrays.length != 2) { 110 | return params; 111 | } else { 112 | params = clientArrays; 113 | } 114 | 115 | } 116 | } 117 | 118 | String id = request.getParameter("client_id"); 119 | String secret = request.getParameter("client_secret"); 120 | 121 | if (header == null && id != null) { 122 | params = new String[]{id, secret}; 123 | } 124 | 125 | 126 | return params; 127 | } 128 | 129 | public ClientDetailsService getClientDetailsService() { 130 | return clientDetailsService; 131 | } 132 | 133 | public void setClientDetailsService(ClientDetailsService clientDetailsService) { 134 | this.clientDetailsService = clientDetailsService; 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/filter/BootPictureCodeAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.filter; 2 | 3 | import club.yuit.oauth.boot.exception.AuthFailureException; 4 | import club.yuit.oauth.boot.support.BootSecurityProperties; 5 | import club.yuit.oauth.boot.support.code.BootCodeService; 6 | import club.yuit.oauth.boot.support.properities.BootBaseLoginProperties; 7 | import org.apache.commons.lang3.StringUtils; 8 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 9 | import org.springframework.util.AntPathMatcher; 10 | import org.springframework.web.filter.OncePerRequestFilter; 11 | 12 | import javax.servlet.FilterChain; 13 | import javax.servlet.ServletException; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | import java.io.IOException; 17 | 18 | /** 19 | * @author yuit 20 | * @date 2019/4/9 16:10 21 | */ 22 | 23 | public class BootPictureCodeAuthenticationFilter extends OncePerRequestFilter { 24 | 25 | 26 | private AntPathMatcher pathMatcher= new AntPathMatcher(); 27 | private BootSecurityProperties properties; 28 | private BootCodeService bootCodeService; 29 | private AuthenticationFailureHandler failureHandler; 30 | 31 | public BootPictureCodeAuthenticationFilter(BootSecurityProperties properties, BootCodeService bootCodeService, AuthenticationFailureHandler failureHandler) { 32 | this.properties = properties; 33 | this.bootCodeService = bootCodeService; 34 | this.failureHandler = failureHandler; 35 | } 36 | 37 | 38 | @Override 39 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { 40 | //本次请求url 41 | String path = request.getRequestURI(); 42 | BootBaseLoginProperties base = this.properties.getBaseLogin(); 43 | 44 | if (pathMatcher.match(base.getLoginProcessUrl(),path)) { 45 | 46 | // 图片验证码值 47 | String pCode = request.getParameter(base.getPictureCodeParameterName()); 48 | String queryString = request.getQueryString(); 49 | String key = request.getParameter("key"); 50 | 51 | if(StringUtils.isBlank(pCode)){ 52 | request.setAttribute("error","error"); 53 | this.failureHandler.onAuthenticationFailure(request,response,new AuthFailureException("验证码错误")); 54 | return; 55 | } 56 | if (!this.bootCodeService.verification(key,pCode,true)){ 57 | this.failureHandler.onAuthenticationFailure(request,response,new AuthFailureException("验证码错误")); 58 | return; 59 | } 60 | } 61 | 62 | 63 | filterChain.doFilter(request,response); 64 | 65 | } 66 | 67 | 68 | 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/handler/BootLoginFailureHandler.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.handler; 2 | 3 | import club.yuit.oauth.boot.support.BootSecurityProperties; 4 | import org.springframework.security.core.AuthenticationException; 5 | import org.springframework.security.web.WebAttributes; 6 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 7 | import org.springframework.stereotype.Component; 8 | 9 | import javax.servlet.ServletException; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | /** 15 | * @author yuit 16 | * @date 2018/11/6 17:45 17 | * 18 | */ 19 | @Component 20 | public class BootLoginFailureHandler implements AuthenticationFailureHandler{ 21 | 22 | private BootSecurityProperties properties; 23 | 24 | public BootLoginFailureHandler(BootSecurityProperties properties) { 25 | this.properties = properties; 26 | } 27 | 28 | @Override 29 | public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { 30 | request.setAttribute("error",exception.getMessage()); 31 | request.getRequestDispatcher(properties.getLoginPage()).forward(request,response); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/mapper/ClientMapper.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.mapper; 2 | 3 | import club.yuit.oauth.boot.entity.Client; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.apache.ibatis.annotations.Select; 7 | import org.springframework.stereotype.Repository; 8 | 9 | /** 10 | * @author yuit 11 | * @date 2018/10/16 10:02 12 | * 13 | **/ 14 | @Repository 15 | public interface ClientMapper extends BaseMapper { 16 | 17 | 18 | @Select("select * from clients where clientId=#{id}") 19 | Client findClientByClientId(@Param("id") String clientId); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.mapper; 2 | 3 | import club.yuit.oauth.boot.entity.User; 4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 5 | import org.apache.ibatis.annotations.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | /** 9 | * @author yuit 10 | * @date 2018/10/9 15:44 11 | * 12 | **/ 13 | @Repository 14 | public interface UserMapper extends BaseMapper { 15 | 16 | 17 | User findByUserName( String username); 18 | 19 | User findUserByMobile(String mobile); 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/BaseResponse.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author yuit 7 | * @date 2018/3/30 20:37 8 | * 9 | */ 10 | @Data 11 | public class BaseResponse { 12 | 13 | private int status; 14 | private String msg; 15 | 16 | protected BaseResponse() { 17 | } 18 | 19 | protected BaseResponse(int status, String msg) { 20 | this.status = status; 21 | this.msg = msg; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/HttpResponse.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import static club.yuit.oauth.boot.response.HttpStatusAndMsg.exs; 4 | 5 | /** 6 | * @author yuit 7 | * @date 2018/3/30 20:37 8 | * 9 | */ 10 | public final class HttpResponse { 11 | 12 | /**--------------------------BaseResponse-------------------------------------------------*/ 13 | public static BaseResponse baseResponse(int status) { 14 | return baseResponse(status, null); 15 | } 16 | 17 | public static BaseResponse baseResponse(int status, String msg) { 18 | 19 | if (msg != null) { 20 | return new BaseResponse(status, msg); 21 | } else { 22 | return new BaseResponse(status, exs.get(status)); 23 | } 24 | } 25 | 26 | public static BaseResponse successResponse(){ 27 | return baseResponse(200); 28 | } 29 | 30 | public static BaseResponse successResponse(String msg){ 31 | return baseResponse(200,msg); 32 | } 33 | 34 | /**--------------------------SimpleResponse-------------------------------------------------*/ 35 | public static SimpleResponse simpleResponse(int status) { 36 | return simpleResponse(status, null, null); 37 | } 38 | 39 | public static SimpleResponse simpleResponse(int status, String msg) { 40 | return simpleResponse(status, msg, null); 41 | } 42 | 43 | public static SimpleResponse simpleResponse(int status, T data) { 44 | return simpleResponse(status, null, data); 45 | } 46 | 47 | public static SimpleResponse simpleResponse(int status, String msg, T data) { 48 | 49 | SimpleResponse response = new SimpleResponse<>(); 50 | response.setStatus(status); 51 | if (msg != null) { 52 | response.setMsg(msg); 53 | } else { 54 | response.setMsg(exs.get(status)); 55 | } 56 | response.setItem(data); 57 | return response; 58 | } 59 | 60 | public static SimpleResponse successSimpleResponse(T data){ 61 | return simpleResponse(200,data); 62 | } 63 | 64 | public static SimpleResponse successSimpleResponse(String msg,T data){ 65 | return simpleResponse(200,msg,data); 66 | } 67 | 68 | /**--------------------------PageAndSortResponse-------------------------------------------------*/ 69 | public static PageAndSortResponse pageAndSortResponse(int status, PageQueryItems query) { 70 | return pageAndSortResponse(status, null, query); 71 | } 72 | 73 | public static PageAndSortResponse pageAndSortResponse(int status, String msg, PageQueryItems query) { 74 | PageAndSortResponse response = new PageAndSortResponse<>(); 75 | response.setCurrentPage(query.getCurrentPage()); 76 | response.setPageSize(query.getPageSize()); 77 | response.setCount(query.getCount()); 78 | response.setStatus(status); 79 | response.setItems(query.getItems()); 80 | if (msg != null) { 81 | response.setMsg(msg); 82 | } else { 83 | response.setMsg(exs.get(status)); 84 | } 85 | 86 | return response; 87 | } 88 | 89 | public static PageAndSortResponse successPageResponse(PageQueryItems items){ 90 | return pageAndSortResponse(200,items); 91 | } 92 | public static PageAndSortResponse successPageResponse(String msg,PageQueryItems items){ 93 | return pageAndSortResponse(200,msg,items); 94 | } 95 | 96 | /**--------------------------ListResponse-------------------------------------------------*/ 97 | public static ListResponse listResponse(int status, Items items) { 98 | return listResponse(status, null, items); 99 | } 100 | 101 | public static ListResponse listResponse(int status, String msg, Items items) { 102 | ListResponse response = new ListResponse<>(); 103 | response.setCount(items.getCount()); 104 | response.setItems(items.getItems()); 105 | 106 | if (msg != null) { 107 | response.setMsg(msg); 108 | } else { 109 | response.setMsg(exs.get(status)); 110 | } 111 | 112 | return response; 113 | 114 | } 115 | 116 | public static ListResponse successListResponse(Items items){ 117 | return listResponse(200,items); 118 | } 119 | 120 | public static ListResponse successListResponse(String msg,Items items){ 121 | return listResponse(200,msg,items); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/HttpStatusAndMsg.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | 7 | /** 8 | * @author yuit 9 | * @date 2018/3/30 20:37 10 | * 11 | */ 12 | public class HttpStatusAndMsg { 13 | 14 | // final 修饰不可继承 15 | public final static Map exs = new HashMap<>(); 16 | 17 | static { 18 | 19 | exs.put(200, "Request Success"); 20 | // 参数问题 21 | exs.put(400, "Bad Request"); 22 | // 未认证 23 | exs.put(401, "NotAuthorization"); 24 | // 找不到ULR 25 | exs.put(404, "Not Found"); 26 | // 请求方法不正确 27 | exs.put(405, "Method Not Allowed"); 28 | // 不支持Media Type 29 | exs.put(415, "Unsupported Media Type"); 30 | //服务器内部错误 31 | exs.put(500, "Internal Server Error"); 32 | //未知错误 33 | exs.put(1000, "UnKnow Error"); 34 | // 未知异常 35 | exs.put(1001, "UnKnowException"); 36 | // 运行时异常 37 | exs.put(1002, "RuntimeException"); 38 | // 类型转换异常 39 | exs.put(1003, "ClassCastException"); 40 | // 空指针异常 41 | exs.put(1004, "NullPointerException"); 42 | // IO 异常 43 | exs.put(1005, "IOException"); 44 | //找不到方法 45 | exs.put(1006, "NoSuchMethodException"); 46 | // 数组越界 47 | exs.put(1007, "IndexOutOfBoundsException"); 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/Items.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2018/8/6 15:56 10 | * 11 | **/ 12 | @Data 13 | public class Items { 14 | 15 | long count; 16 | List items; 17 | 18 | public Items() { 19 | 20 | } 21 | 22 | public Items(long count, List items) { 23 | this.count = count; 24 | this.items = items; 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/ListResponse.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author yuit 11 | * @date 2018/3/30 20:37 12 | * 13 | */ 14 | @Getter 15 | @Setter 16 | public class ListResponse extends BaseResponse { 17 | 18 | private long count; 19 | private List items; 20 | 21 | protected ListResponse(){ 22 | 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/OrderType.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | /** 4 | * @author yuit 5 | * @date time 2018/8/6 15:56 6 | * 7 | **/ 8 | public enum OrderType { 9 | 10 | ASC, 11 | DESC 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/PageAndSortResponse.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author yuit 11 | * @date 2018/3/30 20:37 12 | * 13 | */ 14 | @Getter 15 | @Setter 16 | public class PageAndSortResponse extends BaseResponse { 17 | 18 | private Integer currentPage; 19 | private Integer pageSize; 20 | private long count; 21 | List items; 22 | 23 | protected PageAndSortResponse(){} 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/PageQueryItems.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2018/8/6 15:56 10 | * 11 | **/ 12 | @Data 13 | public class PageQueryItems { 14 | 15 | private Integer currentPage; 16 | private Integer pageSize; 17 | private Long count; 18 | private List items; 19 | 20 | public PageQueryItems(Integer currentPage, Integer pageSize, Long count, List items) { 21 | this.currentPage = currentPage; 22 | this.pageSize = pageSize; 23 | this.count = count; 24 | this.items = items; 25 | } 26 | 27 | public PageQueryItems() { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/response/SimpleResponse.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.response; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2018/3/30 20:37 10 | * 11 | */ 12 | @Getter 13 | @Setter 14 | public class SimpleResponse extends BaseResponse { 15 | 16 | private T item; 17 | 18 | protected SimpleResponse() { 19 | } 20 | 21 | protected SimpleResponse(int status, String msg, T item) { 22 | super(status, msg); 23 | this.item = item; 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/service/IClientService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.service; 2 | 3 | import club.yuit.oauth.boot.entity.Client; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2018/10/16 10:03 10 | * 11 | **/ 12 | 13 | public interface IClientService extends IService { 14 | Client findClientByClientId(@Param("id") String clientId); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/service/IUserService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.service; 2 | 3 | import club.yuit.oauth.boot.entity.User; 4 | import com.baomidou.mybatisplus.extension.service.IService; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author yuit 10 | * @date 2018/10/9 16:55 11 | * 12 | **/ 13 | public interface IUserService extends IService { 14 | 15 | User findByUserName(String userName); 16 | User findUserByMobile(String mobile); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/service/impl/ClientServiceImpl.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.service.impl; 2 | 3 | import club.yuit.oauth.boot.entity.Client; 4 | import club.yuit.oauth.boot.mapper.ClientMapper; 5 | import club.yuit.oauth.boot.service.IClientService; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import org.springframework.stereotype.Service; 8 | 9 | /** 10 | * @author yuit 11 | * @date 2018/10/16 10:06 12 | * 13 | **/ 14 | @Service 15 | public class ClientServiceImpl extends ServiceImpl implements IClientService { 16 | 17 | 18 | @Override 19 | public Client findClientByClientId(String clientId) { 20 | return this.baseMapper.findClientByClientId(clientId); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.service.impl; 2 | 3 | import club.yuit.oauth.boot.entity.User; 4 | import club.yuit.oauth.boot.mapper.UserMapper; 5 | import club.yuit.oauth.boot.service.IUserService; 6 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * @author yuit 14 | * @date 2018/10/9 16:56 15 | * 16 | **/ 17 | @Service 18 | public class UserServiceImpl extends ServiceImpl implements IUserService { 19 | 20 | @Override 21 | public User findByUserName(String userName) { 22 | return this.baseMapper.findByUserName(userName); 23 | } 24 | 25 | @Override 26 | public User findUserByMobile(String mobile) { 27 | return this.baseMapper.findUserByMobile(mobile); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/BootSecurityProperties.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support; 2 | 3 | import club.yuit.oauth.boot.support.properities.*; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.boot.context.properties.NestedConfigurationProperty; 9 | import org.springframework.context.annotation.Configuration; 10 | 11 | /** 12 | * @author yuit 13 | * @date 2018/10/19 9:44 14 | * 15 | * 配置 16 | */ 17 | @Configuration 18 | @EnableConfigurationProperties 19 | @ConfigurationProperties(prefix = "boot.oauth") 20 | @Getter 21 | @Setter 22 | public class BootSecurityProperties { 23 | 24 | 25 | // 登录页面 26 | private String loginPage="/auth/login"; 27 | 28 | /** 29 | * 获取验证码 30 | */ 31 | private String codePath = "/auth/code"; 32 | 33 | 34 | // 验证码存储位置 {session},{redis} 35 | private CodeStoreType codeStoreType = CodeStoreType.session; 36 | 37 | 38 | // redis 存储的验证码过期时间 单位 秒 39 | private long codeExpireTime = 360; 40 | 41 | 42 | /** 43 | * 日志输出等级,默认 INFO {@NestedConfigurationProperty} 生成嵌套类的配置元数据信息 44 | * 更友好的提示 45 | */ 46 | @NestedConfigurationProperty 47 | private BootLogLevelProperties logging = new BootLogLevelProperties(); 48 | 49 | /** 50 | * 短信验证码登录相关配置 51 | */ 52 | @NestedConfigurationProperty 53 | private BootSmsLoginProperties smsLogin = new BootSmsLoginProperties(); 54 | 55 | /** 56 | * 用户名密码登录相关配置 57 | */ 58 | @NestedConfigurationProperty 59 | private BootBaseLoginProperties baseLogin = new BootBaseLoginProperties(); 60 | 61 | /** 62 | * oauth2 相关配置 63 | */ 64 | @NestedConfigurationProperty 65 | private BootOAuth2Properties oauth2 = new BootOAuth2Properties(); 66 | 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/BootSmsUserDetailService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support; 2 | 3 | import club.yuit.oauth.boot.service.IUserService; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | import org.springframework.security.core.userdetails.UserDetailsService; 6 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author yuit 11 | * @date 2019/11/26 9:38 12 | **/ 13 | @Component 14 | public class BootSmsUserDetailService implements UserDetailsService { 15 | 16 | private IUserService userService; 17 | 18 | public BootSmsUserDetailService(IUserService userService) { 19 | this.userService = userService; 20 | } 21 | 22 | @Override 23 | public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException { 24 | return userService.findUserByMobile(mobile); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/BootUserDetailService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support; 2 | 3 | import club.yuit.oauth.boot.entity.User; 4 | import club.yuit.oauth.boot.service.IUserService; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 13 | import org.springframework.stereotype.Component; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | 18 | /** 19 | * @author yuit 20 | * @date time 2018/10/11 9:13 21 | * 22 | **/ 23 | @Component 24 | public final class BootUserDetailService implements UserDetailsService { 25 | 26 | @Autowired 27 | private IUserService userService; 28 | 29 | private Logger logger = LoggerFactory.getLogger(getClass()); 30 | 31 | @Override 32 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 33 | 34 | User user= this.userService.findByUserName(username); 35 | 36 | GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER"); 37 | 38 | List authorities = new ArrayList<>(); 39 | authorities.add(authority); 40 | user.setAuthorities(authorities); 41 | 42 | if(user==null) { 43 | throw new UsernameNotFoundException("用户名不存在"); 44 | } 45 | 46 | return user; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/DefaultBeanName.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support; 2 | 3 | /** 4 | * @author yuit 5 | * @date 2019/11/26 16:01 6 | **/ 7 | public class DefaultBeanName { 8 | 9 | public final static String DEFAULT_PICTURE_CODE_GENERATOR_BEAN = "club.yuit.oauth.boot.support.code.picture.DefaultPictureCodeGenerator"; 10 | public final static String DEFAULT_SMS_CODE_GENERATOR_BEAN = "club.yuit.oauth.boot.support.code.picture.DefaultSmsCodeGenerator"; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/code/BootCodeService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.code; 2 | 3 | /** 4 | * @author yuit 5 | * @date 2019/4/9 17:43 6 | */ 7 | public interface BootCodeService { 8 | /** 9 | * 获取验证码 10 | * @param key 11 | * @return 12 | */ 13 | T getCodeValue(String key); 14 | 15 | /** 16 | * 设置验证码值 17 | * @param key 18 | * @param value 19 | */ 20 | void setCodeValue(String key, T value); 21 | 22 | /** 23 | * 校验验证码 24 | * @param key key 25 | * @param value 值 26 | * @param ignore 是否忽略大小写 27 | * @return 28 | */ 29 | boolean verification(String key,T value,boolean ignore); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/code/RedisCodeService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.code; 2 | 3 | import org.springframework.data.redis.core.StringRedisTemplate; 4 | 5 | import java.util.concurrent.TimeUnit; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2019/11/20 15:37 10 | **/ 11 | public class RedisCodeService implements BootCodeService { 12 | 13 | private StringRedisTemplate template; 14 | private long expire; 15 | 16 | public RedisCodeService(StringRedisTemplate template, long expire) { 17 | this.template = template; 18 | this.expire = expire; 19 | } 20 | 21 | @Override 22 | public String getCodeValue(String key) { 23 | return this.template.opsForValue().get(key); 24 | } 25 | 26 | @Override 27 | public void setCodeValue(String key, String value) { 28 | this.template.opsForValue().set(key, value, this.expire, TimeUnit.SECONDS); 29 | } 30 | 31 | 32 | @Override 33 | public boolean verification(String key, String value, boolean ignore) { 34 | 35 | if (value == null || value.trim().equals("")) { 36 | return false; 37 | } 38 | 39 | Boolean has = this.template.hasKey(key); 40 | 41 | if (has == null || !has) { 42 | return false; 43 | } 44 | 45 | Long expire = this.template.getExpire(key); 46 | 47 | if (expire == null || expire <= 0) { 48 | return false; 49 | } 50 | 51 | String tmpValue = this.getCodeValue(key); 52 | 53 | if (ignore) { 54 | return value.equalsIgnoreCase(tmpValue); 55 | } 56 | return value.equals(tmpValue); 57 | } 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/code/SessionCodeService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.code; 2 | 3 | import club.yuit.oauth.boot.support.code.BootCodeService; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.web.context.request.RequestAttributes; 7 | import org.springframework.web.context.request.RequestContextHolder; 8 | import org.springframework.web.context.request.ServletRequestAttributes; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpSession; 12 | import java.util.Objects; 13 | 14 | /** 15 | * @author yuit 16 | * @date 2019/4/9 18:09 17 | */ 18 | @Slf4j 19 | public class SessionCodeService implements BootCodeService { 20 | 21 | 22 | 23 | 24 | 25 | public SessionCodeService() { 26 | } 27 | 28 | @Override 29 | public String getCodeValue(String key){ 30 | HttpSession session = this.getSession(); 31 | if (session==null){ 32 | log.error("当前请求获取不到Session"); 33 | return null; 34 | } 35 | return (String)session.getAttribute(key); 36 | } 37 | 38 | @Override 39 | public void setCodeValue(String key, String value) { 40 | HttpSession session = this.getSession(); 41 | if (session==null){ 42 | log.error("当前请求获取不到Session"); 43 | return; 44 | } 45 | session.setAttribute(key,value); 46 | } 47 | 48 | @Override 49 | public boolean verification(String key, String value,boolean ignore) { 50 | 51 | if (value==null||value.trim().equals("")){ 52 | return false; 53 | } 54 | 55 | String valueTmp =this.getCodeValue(key); 56 | if (ignore){ 57 | return value.equalsIgnoreCase(valueTmp); 58 | } 59 | return value.equals(valueTmp); 60 | } 61 | 62 | private HttpSession getSession() { 63 | 64 | HttpServletRequest request = ((ServletRequestAttributes)(RequestContextHolder.getRequestAttributes())).getRequest(); 65 | 66 | if (request==null) { 67 | log.error("当前请求获取不到Session"); 68 | return null; 69 | } 70 | return request.getSession(); 71 | } 72 | 73 | 74 | 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/code/VerificationCode.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.code; 2 | 3 | import lombok.Data; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2018/10/19 10:42 10 | * 11 | */ 12 | @Getter 13 | @Setter 14 | public class VerificationCode { 15 | 16 | private T content; 17 | private long expirationTime; 18 | 19 | public VerificationCode() { 20 | } 21 | 22 | 23 | public VerificationCode(T content, long expirationTime) { 24 | this.content = content; 25 | this.expirationTime = expirationTime; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/code/VerificationCodeGenerator.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.code; 2 | 3 | import org.springframework.web.context.request.ServletWebRequest; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2018/10/19 17:42 10 | * 11 | */ 12 | public interface VerificationCodeGenerator { 13 | 14 | /** 15 | * 生成验证码 16 | * @return 17 | */ 18 | VerificationCode generator(T key) throws Exception; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/code/picture/DefaultPictureCodeGenerator.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.code.picture; 2 | 3 | import club.yuit.oauth.boot.response.HttpResponse; 4 | import club.yuit.oauth.boot.support.BootSecurityProperties; 5 | import club.yuit.oauth.boot.support.DefaultBeanName; 6 | import club.yuit.oauth.boot.support.code.BootCodeService; 7 | import club.yuit.oauth.boot.support.code.VerificationCode; 8 | import club.yuit.oauth.boot.support.code.VerificationCodeGenerator; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.imageio.ImageIO; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.awt.*; 14 | import java.awt.geom.AffineTransform; 15 | import java.awt.image.BufferedImage; 16 | import java.io.IOException; 17 | import java.io.OutputStream; 18 | import java.util.Arrays; 19 | import java.util.Random; 20 | 21 | /** 22 | * @author yuit 23 | * @date 2019/4/10 16:44 24 | */ 25 | @Component(DefaultBeanName.DEFAULT_PICTURE_CODE_GENERATOR_BEAN) 26 | public class DefaultPictureCodeGenerator implements VerificationCodeGenerator { 27 | 28 | private static final String SOURCE_CODES = "123456789ABCDEFGHIJKLMNOBQRSTUVWXYZ"; 29 | private static int height = 40; 30 | private static int width = 95; 31 | private static Random random = new Random(); 32 | private BootSecurityProperties properties; 33 | private BootCodeService codeService; 34 | 35 | public DefaultPictureCodeGenerator(BootSecurityProperties properties, BootCodeService codeService) { 36 | this.properties = properties; 37 | this.codeService=codeService; 38 | } 39 | 40 | public VerificationCode generator(String key) throws IOException { 41 | 42 | String code = createCodeStr(4); 43 | 44 | int verifySize = code.length(); 45 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 46 | Random rand = new Random(); 47 | Graphics2D g2 = image.createGraphics(); 48 | g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 49 | Color[] colors = new Color[5]; 50 | Color[] colorSpaces = new Color[]{Color.WHITE, Color.CYAN, 51 | Color.GRAY, Color.LIGHT_GRAY, Color.MAGENTA, Color.ORANGE, 52 | Color.PINK, Color.YELLOW}; 53 | float[] fractions = new float[colors.length]; 54 | for (int i = 0; i < colors.length; i++) { 55 | colors[i] = colorSpaces[rand.nextInt(colorSpaces.length)]; 56 | fractions[i] = rand.nextFloat(); 57 | } 58 | Arrays.sort(fractions); 59 | // 设置边框色 60 | g2.setColor(Color.GRAY); 61 | g2.fillRect(0, 0, width, height); 62 | 63 | Color c = getRandColor(200, 250); 64 | // 设置背景色 65 | g2.setColor(c); 66 | g2.fillRect(0, 2, width, height - 4); 67 | 68 | //绘制干扰线 69 | Random random = new Random(); 70 | // 设置线条的颜色 71 | g2.setColor(getRandColor(160, 200)); 72 | for (int i = 0; i < 20; i++) { 73 | int x = random.nextInt(width - 1); 74 | int y = random.nextInt(height - 1); 75 | int xl = random.nextInt(6) + 1; 76 | int yl = random.nextInt(12) + 1; 77 | g2.drawLine(x, y, x + xl + 40, y + yl + 20); 78 | } 79 | 80 | // 添加噪点 81 | // 噪声率 82 | float yawpRate = 0.05f; 83 | int area = (int) (yawpRate * width * height); 84 | for (int i = 0; i < area; i++) { 85 | int x = random.nextInt(width); 86 | int y = random.nextInt(height); 87 | int rgb = getRandomIntColor(); 88 | image.setRGB(x, y, rgb); 89 | } 90 | 91 | g2.setColor(getRandColor(100, 160)); 92 | int fontSize = height - 4; 93 | Font font = new Font("Algerian", Font.ITALIC, fontSize); 94 | g2.setFont(font); 95 | char[] chars = code.toCharArray(); 96 | for (int i = 0; i < verifySize; i++) { 97 | AffineTransform affine = new AffineTransform(); 98 | affine.setToRotation(Math.PI / 4 * rand.nextDouble() * (rand.nextBoolean() ? 1 : -1), (width / verifySize) * i + fontSize / 2, height / 2); 99 | g2.setTransform(affine); 100 | g2.drawChars(chars, i, 1, ((width - 10) / verifySize) * i + 5, height / 2 + fontSize / 2 - 10); 101 | } 102 | 103 | g2.dispose(); 104 | codeService.setCodeValue(key, code); 105 | return new VerificationCode(image,properties.getCodeExpireTime()); 106 | } 107 | 108 | private static String createCodeStr(int codeLength) { 109 | Random random = new Random(); 110 | StringBuilder builder = new StringBuilder(); 111 | for (int i = 0; i < codeLength; i++) { 112 | int key = random.nextInt(SOURCE_CODES.length() - 1); 113 | builder.append(SOURCE_CODES.charAt(key)); 114 | } 115 | 116 | return builder.toString(); 117 | } 118 | 119 | private static int[] getRandomRgb() { 120 | int[] rgb = new int[3]; 121 | for (int i = 0; i < 3; i++) { 122 | rgb[i] = random.nextInt(255); 123 | } 124 | return rgb; 125 | } 126 | 127 | private static int getRandomIntColor() { 128 | int[] rgb = getRandomRgb(); 129 | int color = 0; 130 | for (int c : rgb) { 131 | color = color << 8; 132 | color = color | c; 133 | } 134 | return color; 135 | } 136 | 137 | 138 | private static Color getRandColor(int fc, int bc) { 139 | 140 | Random random = new Random(); 141 | 142 | if (fc > 255) { 143 | fc = 255; 144 | } 145 | if (bc > 255) { 146 | bc = 255; 147 | } 148 | int r = fc + random.nextInt(bc - fc); 149 | int g = fc + random.nextInt(bc - fc); 150 | int b = fc + random.nextInt(bc - fc); 151 | return new Color(r, g, b); 152 | } 153 | 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/code/sms/DefaultSmsCodeGenerator.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.code.sms; 2 | 3 | import club.yuit.oauth.boot.support.BootSecurityProperties; 4 | import club.yuit.oauth.boot.support.DefaultBeanName; 5 | import club.yuit.oauth.boot.support.code.BootCodeService; 6 | import club.yuit.oauth.boot.support.code.VerificationCode; 7 | import club.yuit.oauth.boot.support.code.VerificationCodeGenerator; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.apache.commons.lang3.RandomStringUtils; 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.springframework.stereotype.Component; 12 | 13 | /** 14 | * @author yuit 15 | * @date 2019/11/26 14:56 16 | **/ 17 | @Component(DefaultBeanName.DEFAULT_SMS_CODE_GENERATOR_BEAN) 18 | @Slf4j 19 | public class DefaultSmsCodeGenerator implements VerificationCodeGenerator { 20 | 21 | private BootSecurityProperties properties; 22 | private BootCodeService codeService; 23 | 24 | private final static String CODE_STR="1234567890"; 25 | 26 | public DefaultSmsCodeGenerator(BootSecurityProperties properties, BootCodeService codeService) { 27 | this.properties = properties; 28 | this.codeService = codeService; 29 | } 30 | 31 | @Override 32 | public VerificationCode generator(String key) throws Exception { 33 | VerificationCode vc = new VerificationCode<>(); 34 | String code = RandomStringUtils.random(6,CODE_STR); 35 | vc.setContent(code); 36 | vc.setExpirationTime(properties.getCodeExpireTime()); 37 | codeService.setCodeValue(key,code); 38 | 39 | log.info("[OAUTH·BOOT]:登录验证码:{},{}分钟内有效",vc.getContent(),vc.getExpirationTime()/60); 40 | 41 | return vc; 42 | } 43 | 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/common/TokenStoreType.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.common; 2 | 3 | /** 4 | * @author yuit 5 | * @date 2018/10/19 10:57 6 | */ 7 | public enum TokenStoreType { 8 | /* 9 | 内存 10 | */ 11 | memory, 12 | /* 13 | redis 14 | */ 15 | redis, 16 | /* 17 | json web token 18 | */ 19 | jwt, 20 | /* 21 | 数据库 22 | */ 23 | jdbc 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/oauth2/BootAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.oauth2; 2 | 3 | import club.yuit.oauth.boot.response.HttpResponse; 4 | import club.yuit.oauth.boot.utils.HttpUtils; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.security.access.AccessDeniedException; 7 | import org.springframework.security.web.access.AccessDeniedHandler; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | 15 | /** 16 | * @author yuit 17 | * @date 2018/11/1 18:15 18 | * 请求拒绝,没有权限 19 | */ 20 | @Component 21 | public class BootAccessDeniedHandler implements AccessDeniedHandler { 22 | @Override 23 | public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException ex) throws IOException, ServletException { 24 | HttpUtils.writer(HttpResponse.baseResponse(HttpStatus.FORBIDDEN.value(),"没有权限"),response); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/oauth2/BootClientDetails.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.oauth2; 2 | 3 | import club.yuit.oauth.boot.entity.Client; 4 | import club.yuit.oauth.boot.utils.CommonUtils; 5 | import lombok.Data; 6 | import org.springframework.security.core.GrantedAuthority; 7 | import org.springframework.security.core.authority.AuthorityUtils; 8 | import org.springframework.security.oauth2.provider.ClientDetails; 9 | 10 | import java.util.Collection; 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | /** 15 | * @author yuit 16 | * @date 2018/10/16 15:36 17 | * 18 | **/ 19 | @Data 20 | @SuppressWarnings("unchecked") 21 | public final class BootClientDetails implements ClientDetails { 22 | 23 | private Client client; 24 | private Set scope; 25 | 26 | public BootClientDetails(Client client) { 27 | this.client = client; 28 | } 29 | 30 | public BootClientDetails() { 31 | } 32 | 33 | @Override 34 | public String getClientId() { 35 | return client.getClientId(); 36 | } 37 | 38 | @Override 39 | public Set getResourceIds() { 40 | return client.getResourceIds()!=null? 41 | CommonUtils.transformStringToSet(client.getResourceIds(),String.class):null; 42 | } 43 | 44 | @Override 45 | public boolean isSecretRequired() { 46 | return client.getIsSecretRequired(); 47 | } 48 | 49 | @Override 50 | public String getClientSecret() { 51 | return client.getClientSecret(); 52 | } 53 | 54 | @Override 55 | public boolean isScoped() { 56 | return client.getIsScoped(); 57 | } 58 | 59 | @Override 60 | public Set getScope() { 61 | 62 | this.scope = client.getScope()!=null? 63 | CommonUtils.transformStringToSet(client.getScope(),String.class):null; 64 | 65 | return client.getScope()!=null? 66 | CommonUtils.transformStringToSet(client.getScope(),String.class):null; 67 | } 68 | 69 | @Override 70 | public Set getAuthorizedGrantTypes() { 71 | return client.getAuthorizedGrantTypes()!=null? 72 | CommonUtils.transformStringToSet(client.getAuthorizedGrantTypes(),String.class):null; 73 | } 74 | 75 | @Override 76 | public Set getRegisteredRedirectUri() { 77 | return client.getRegisteredRedirectUri()!=null? 78 | CommonUtils.transformStringToSet(client.getRegisteredRedirectUri(),String.class):null; 79 | } 80 | 81 | @Override 82 | public Collection getAuthorities() { 83 | return (client.getAuthorities()!=null&&client.getAuthorities().trim().length()>0)? 84 | AuthorityUtils.commaSeparatedStringToAuthorityList(client.getAuthorities()):null; 85 | } 86 | 87 | @Override 88 | public Integer getAccessTokenValiditySeconds() { 89 | return client.getAccessTokenValiditySeconds(); 90 | } 91 | 92 | @Override 93 | public Integer getRefreshTokenValiditySeconds() { 94 | return client.getRefreshTokenValiditySeconds(); 95 | } 96 | 97 | @Override 98 | public boolean isAutoApprove(String scope) { 99 | return this.client.getIsAutoApprove()==null ? false: this 100 | .client.getIsAutoApprove(); 101 | } 102 | 103 | @Override 104 | public Map getAdditionalInformation() { 105 | return null; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/oauth2/BootClientDetailsService.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.oauth2; 2 | 3 | import club.yuit.oauth.boot.entity.Client; 4 | import club.yuit.oauth.boot.service.IClientService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.oauth2.provider.ClientDetails; 7 | import org.springframework.security.oauth2.provider.ClientDetailsService; 8 | import org.springframework.security.oauth2.provider.ClientRegistrationException; 9 | import org.springframework.stereotype.Component; 10 | 11 | /** 12 | * @author yuit 13 | * @date 2018/10/16 9:22 14 | * 15 | **/ 16 | @Component 17 | public final class BootClientDetailsService implements ClientDetailsService { 18 | 19 | @Autowired 20 | private IClientService clientService; 21 | 22 | @Override 23 | public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { 24 | 25 | Client client = this.clientService.findClientByClientId(clientId); 26 | 27 | if(client==null){ 28 | throw new ClientRegistrationException("客户端不存在"); 29 | } 30 | BootClientDetails details=new BootClientDetails(client); 31 | 32 | return details; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/oauth2/BootOAuth2AuthExceptionEntryPoint.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.oauth2; 2 | 3 | import club.yuit.oauth.boot.response.HttpResponse; 4 | import club.yuit.oauth.boot.utils.HttpUtils; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; 9 | import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; 10 | import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; 11 | import org.springframework.security.web.AuthenticationEntryPoint; 12 | import org.springframework.stereotype.Component; 13 | 14 | import javax.servlet.ServletException; 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | import java.io.IOException; 18 | 19 | /** 20 | * @author yuit 21 | * @date 2018/11/2 10:48 22 | * 23 | */ 24 | @Component 25 | public class BootOAuth2AuthExceptionEntryPoint extends OAuth2AuthenticationEntryPoint { 26 | @Override 27 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { 28 | HttpUtils.writer(HttpResponse.baseResponse(HttpStatus.UNAUTHORIZED.value(),e.getMessage()),response); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/oauth2/BootOAuth2Exception.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.oauth2; 2 | 3 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 4 | import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; 5 | 6 | /** 7 | * @author yuit 8 | * @date 2018/11/5 18:00 9 | * 10 | */ 11 | @JsonSerialize(using = BootOAuthExceptionJacksonSerializer.class) 12 | public class BootOAuth2Exception extends OAuth2Exception { 13 | 14 | 15 | 16 | public BootOAuth2Exception(String msg, Throwable t) { 17 | super(msg, t); 18 | 19 | } 20 | 21 | public BootOAuth2Exception(String msg) { 22 | super(msg); 23 | 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/oauth2/BootOAuth2WebResponseExceptionTranslator.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.oauth2; 2 | 3 | import org.springframework.http.HttpHeaders; 4 | import org.springframework.http.HttpStatus; 5 | import org.springframework.http.ResponseEntity; 6 | import org.springframework.security.access.AccessDeniedException; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer; 9 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 10 | import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException; 11 | import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; 12 | import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; 13 | import org.springframework.security.web.util.ThrowableAnalyzer; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.web.HttpRequestMethodNotSupportedException; 16 | 17 | import java.io.IOException; 18 | 19 | /** 20 | * @author yuit 21 | * @date 2018/11/2 9:14 22 | * 23 | */ 24 | @Component("bootWebResponseExceptionTranslator") 25 | public class BootOAuth2WebResponseExceptionTranslator implements WebResponseExceptionTranslator { 26 | 27 | private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer(); 28 | 29 | @Override 30 | public ResponseEntity translate(Exception e) throws Exception { 31 | 32 | // Try to extract a SpringSecurityException from the stacktrace 33 | Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e); 34 | 35 | // 异常栈获取 OAuth2Exception 异常 36 | Exception ase = (OAuth2Exception) throwableAnalyzer.getFirstThrowableOfType( 37 | OAuth2Exception.class, causeChain); 38 | 39 | // 异常栈中有OAuth2Exception 40 | if (ase != null) { 41 | return handleOAuth2Exception((OAuth2Exception) ase); 42 | } 43 | 44 | ase = (AuthenticationException) throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, 45 | causeChain); 46 | if (ase != null) { 47 | return handleOAuth2Exception(new UnauthorizedException(e.getMessage(), e)); 48 | } 49 | 50 | ase = (AccessDeniedException) throwableAnalyzer 51 | .getFirstThrowableOfType(AccessDeniedException.class, causeChain); 52 | if (ase instanceof AccessDeniedException) { 53 | return handleOAuth2Exception(new ForbiddenException(ase.getMessage(), ase)); 54 | } 55 | 56 | ase = (HttpRequestMethodNotSupportedException) throwableAnalyzer 57 | .getFirstThrowableOfType(HttpRequestMethodNotSupportedException.class, causeChain); 58 | if (ase instanceof HttpRequestMethodNotSupportedException) { 59 | return handleOAuth2Exception(new MethodNotAllowed(ase.getMessage(), ase)); 60 | } 61 | 62 | // 不包含上述异常则服务器内部错误 63 | return handleOAuth2Exception(new ServerErrorException(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase(), e)); 64 | } 65 | 66 | private ResponseEntity handleOAuth2Exception(OAuth2Exception e) throws IOException { 67 | 68 | int status = e.getHttpErrorCode(); 69 | HttpHeaders headers = new HttpHeaders(); 70 | headers.set("Cache-Control", "no-store"); 71 | headers.set("Pragma", "no-cache"); 72 | if (status == HttpStatus.UNAUTHORIZED.value() || (e instanceof InsufficientScopeException)) { 73 | headers.set("WWW-Authenticate", String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, e.getSummary())); 74 | } 75 | 76 | BootOAuth2Exception exception = new BootOAuth2Exception(e.getMessage(), e); 77 | 78 | ResponseEntity response = new ResponseEntity(exception, headers, 79 | HttpStatus.valueOf(status)); 80 | 81 | return response; 82 | 83 | } 84 | 85 | public void setThrowableAnalyzer(ThrowableAnalyzer throwableAnalyzer) { 86 | this.throwableAnalyzer = throwableAnalyzer; 87 | } 88 | 89 | @SuppressWarnings("serial") 90 | private static class ForbiddenException extends OAuth2Exception { 91 | 92 | public ForbiddenException(String msg, Throwable t) { 93 | super(msg, t); 94 | } 95 | 96 | public String getOAuth2ErrorCode() { 97 | return "access_denied"; 98 | } 99 | 100 | public int getHttpErrorCode() { 101 | return 403; 102 | } 103 | 104 | } 105 | 106 | @SuppressWarnings("serial") 107 | private static class ServerErrorException extends OAuth2Exception { 108 | 109 | public ServerErrorException(String msg, Throwable t) { 110 | super(msg, t); 111 | } 112 | 113 | public String getOAuth2ErrorCode() { 114 | return "server_error"; 115 | } 116 | 117 | public int getHttpErrorCode() { 118 | return 500; 119 | } 120 | 121 | } 122 | 123 | @SuppressWarnings("serial") 124 | private static class UnauthorizedException extends OAuth2Exception { 125 | 126 | public UnauthorizedException(String msg, Throwable t) { 127 | super(msg, t); 128 | } 129 | 130 | public String getOAuth2ErrorCode() { 131 | return "unauthorized"; 132 | } 133 | 134 | public int getHttpErrorCode() { 135 | return 401; 136 | } 137 | 138 | } 139 | 140 | @SuppressWarnings("serial") 141 | private static class MethodNotAllowed extends OAuth2Exception { 142 | 143 | public MethodNotAllowed(String msg, Throwable t) { 144 | super(msg, t); 145 | } 146 | 147 | public String getOAuth2ErrorCode() { 148 | return "method_not_allowed"; 149 | } 150 | 151 | public int getHttpErrorCode() { 152 | return 405; 153 | } 154 | 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/oauth2/BootOAuthExceptionJacksonSerializer.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.oauth2; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.databind.SerializerProvider; 5 | import com.fasterxml.jackson.databind.ser.std.StdSerializer; 6 | import org.springframework.web.util.HtmlUtils; 7 | 8 | import java.io.IOException; 9 | import java.util.Map; 10 | 11 | /** 12 | * @author yuit 13 | * @date 2018/11/5 18:01 14 | * 15 | */ 16 | public class BootOAuthExceptionJacksonSerializer extends StdSerializer { 17 | 18 | protected BootOAuthExceptionJacksonSerializer() { 19 | super(BootOAuth2Exception.class); 20 | } 21 | 22 | @Override 23 | public void serialize(BootOAuth2Exception value, JsonGenerator jgen, SerializerProvider serializerProvider) throws IOException { 24 | jgen.writeStartObject(); 25 | jgen.writeObjectField("status", value.getHttpErrorCode()); 26 | String errorMessage = value.getOAuth2ErrorCode(); 27 | if (errorMessage != null) { 28 | errorMessage = HtmlUtils.htmlEscape(errorMessage); 29 | } 30 | jgen.writeStringField("msg", errorMessage); 31 | if (value.getAdditionalInformation()!=null) { 32 | for (Map.Entry entry : value.getAdditionalInformation().entrySet()) { 33 | String key = entry.getKey(); 34 | String add = entry.getValue(); 35 | jgen.writeStringField(key, add); 36 | } 37 | } 38 | jgen.writeEndObject(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/properities/BootBaseLoginProperties.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.properities; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author yuit 8 | * @date 2019/11/26 12:17 9 | **/ 10 | @Getter 11 | @Setter 12 | public class BootBaseLoginProperties { 13 | private String loginProcessUrl="/authentication/base"; 14 | private String pictureCodeParameterName="p_code"; 15 | private String usernameParameterName = "username"; 16 | private String passwordParameterName = "password"; 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/properities/BootLogLevelProperties.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.properities; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import lombok.experimental.Accessors; 6 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 7 | 8 | import java.io.Serializable; 9 | 10 | /** 11 | * @author yuit 12 | * @date 2018/10/19 16:30 13 | * 14 | */ 15 | @Getter 16 | @Setter 17 | public class BootLogLevelProperties implements Serializable { 18 | private String level = "INFO"; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/properities/BootOAuth2Properties.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.properities; 2 | 3 | import club.yuit.oauth.boot.support.common.TokenStoreType; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | /** 8 | * @author yuit 9 | * @date 2019/11/26 12:19 10 | **/ 11 | @Getter 12 | @Setter 13 | public class BootOAuth2Properties { 14 | /** 15 | * 定义token存储类型 16 | */ 17 | private TokenStoreType tokenStoreType = TokenStoreType.memory; 18 | 19 | private String tokenSigningKey = "OAUTHBOOT@IUY09&098#UIOKNJJ-YUIT.CLUB"; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/properities/BootSmsLoginProperties.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.properities; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | /** 7 | * @author yuit 8 | * @date 2018/10/19 17:34 9 | * 10 | */ 11 | @Getter 12 | @Setter 13 | public class BootSmsLoginProperties { 14 | 15 | private Integer length = 4; 16 | private String mobileParameterName = "mobile"; 17 | private String codeParameterName = "code"; 18 | private String loginProcessUrl="/authentication/mobile"; 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/support/properities/CodeStoreType.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.support.properities; 2 | 3 | /** 4 | * @author yuit 5 | * @date 2019/11/26 15:33 6 | **/ 7 | public enum CodeStoreType { 8 | session,redis 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/club/yuit/oauth/boot/utils/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot.utils; 2 | 3 | import club.yuit.oauth.boot.response.BaseResponse; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | 6 | import javax.servlet.http.HttpServletResponse; 7 | import java.io.IOException; 8 | 9 | /** 10 | * @author yuit 11 | * @date 2018/11/5 16:34 12 | * 13 | */ 14 | public class HttpUtils { 15 | 16 | public static void writer(BaseResponse bs, HttpServletResponse response) throws IOException { 17 | response.setContentType("application/json,charset=utf-8"); 18 | response.setStatus(bs.getStatus()); 19 | ObjectMapper objectMapper = new ObjectMapper(); 20 | objectMapper.writeValue(response.getOutputStream(),bs); 21 | } 22 | 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8000 3 | # servlet: 4 | # context-path: /api/v1 5 | 6 | spring: 7 | application: 8 | name: boot-cli 9 | # mysql 配置 10 | datasource: 11 | username: dev 12 | password: Sys@gzu123+ 13 | driver-class-name: com.mysql.cj.jdbc.Driver 14 | url: jdbc:mysql://172.16.2.103:3306/boot?useUnicode=true&characterEncoding=utf-8&useSSL=false 15 | type: com.alibaba.druid.pool.DruidDataSource 16 | #redis 配置 17 | redis: 18 | host: 172.16.2.104 19 | port: 6379 20 | password: Sys@redis123+ 21 | jedis: 22 | pool: 23 | max-active: 8 # 连接词最大链接数 24 | max-wait: -1 # 连接池最大阻塞等待时间(负数代表没有限制) 25 | max-idle: 8 # 连接池最大空闲连接数 26 | min-idle: 0 # 连接池最小空闲连接数 27 | timeout: 10000 # 链接超时时间 (ms),连接时间小会导致连接超时 28 | # 模板引擎配置 29 | thymeleaf: 30 | prefix: classpath:/views/ 31 | suffix: .html 32 | cache: false 33 | mvc: 34 | throw-exception-if-no-handler-found: true 35 | 36 | 37 | #logging.level.org.springframework.security: DEBUG 38 | management: 39 | securit: 40 | enabled: true 41 | 42 | mybatis-plus: 43 | mapper-locations: classpath:/mapper/*Mapper.xml # mapper 文件路径 44 | type-aliases-package: club.yuit.oauth.boot.entity 45 | configuration: 46 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 47 | global-config: 48 | db-config: 49 | id-type: uuid 50 | db-type: mysql # 3.0 版本的必须配置 不然无法启动 nested exception is com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Error: GlobalConfigUtils setMetaData Fail ! Cause:java.lang.NullPointerException 51 | boot: 52 | oauth: 53 | oauth2: 54 | token-store-type: jwt 55 | token-signing-key: 123123 56 | code-store-type: redis 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/resources/statics/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/favicon.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/layer/theme/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/layer/theme/default/icon-ext.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/layer/theme/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/layer/theme/default/icon.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/layer/theme/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/layer/theme/default/loading-0.gif -------------------------------------------------------------------------------- /src/main/resources/statics/libs/layer/theme/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/layer/theme/default/loading-1.gif -------------------------------------------------------------------------------- /src/main/resources/statics/libs/layer/theme/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/layer/theme/default/loading-2.gif -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/fonts/nucleo-license.md: -------------------------------------------------------------------------------- 1 | # Standard License - nucleoapp.com 2 | 3 | Github repo: https://github.com/NucleoApp/license-standard 4 | 5 | By purchasing Nucleo you are being granted a license to use Nucleo icons (including the custom Nucleo icons created through the Nucleo applications) for specific uses under certain conditions. 6 | 7 | You have rights to use Nucleo icons in unlimited personal and commercial projects for yourself or a client. Even if you don't renew the Basic license, you can still use the source files for as many projects as you want. 8 | 9 | For each project, you can use a maximum of 250 Nucleo icons (intended per unique style: for example if you're using the same icon in both the outline and glyph styles, or in 2 different sizes, you're using 2 icons). 10 | 11 | By purchasing Nucleo, you have the right to: 12 | 13 | - Use Nucleo icons in unlimited personal and commercial projects. 14 | - Use Nucleo icons in application/website/print/mobile/logo design. 15 | - Modify Nucleo icons to create you own icon variations. 16 | 17 | You don't have the right to: 18 | 19 | - Sublicense, resell, share, transfer, or otherwise redistribute Nucleo icons (even for free or within a more complex downloadable file). 20 | - Use more than 250 Nucleo icons in a single project. 21 | - Use Nucleo icons in a product that is directly competitive with Nucleo. 22 | 23 | ## Freelance Projects & Contracted work 24 | If you’re working on one or more projects for a client, you can share with your client a maximum of 250 Nucleo icons per project. You can’t share Nucleo source files, unless the client purchases a Nucleo license. 25 | 26 | If the End Product you (or the team you’ve been part of) have created for the client is a product offered for sale, and the Nucleo icons contribute to the core value of the product being sold/shared, your client will have to buy an Extended License. 27 | 28 | ## End Product Users 29 | If you're using Nucleo icons in apps, installable items or online products/services, there's no limit to the number of users/customers that can use the product you're developing (e.g. if you're developing a web application and you're using Nucleo icons throughout the design, there's no limit to the number of active users of the application). 30 | 31 | ## Templates, Themes, UI Kits & Plugins 32 | If you’re using Nucleo icons in templates, themes or plugins offered for sale, or for free, (e.g. UI kits, Wordpress Themes, HTML/CSS Templates), you can include up to 100 icons in the downloadable source files. This limitation applies to the icon fonts as well. 33 | 34 | The downloadable source file has to include [Nucleo license](https://github.com/NucleoApp/license-standard). No attribution or link back required, however any credit will be much appreciated. 35 | 36 | If Nucleo icons contribute to the core value of the template, theme or plugin sold/shared (e.g. a theme builder where users can browse Nucleo icons and pick the ones to include in their design), you will need an Extended License. 37 | 38 | ## Open source projects 39 | If you’re using Nucleo icons in open source projects, you can include up to 100 icons in the downloadable source files. This limitation applies to the icon fonts as well. 40 | 41 | The downloadable source file has to include [Nucleo license](https://github.com/NucleoApp/license-standard). No attribution or link back required, however any credit will be much appreciated. 42 | 43 | If Nucleo icons contribute to the core value of the open source project (e.g. a CMS where users can browse Nucleo icons and pick the ones to include in their design), you will need an Extended License. 44 | 45 | ## Extended License 46 | If you're interested in using Nucleo icons in items offered for sale (or for free) where the Nucleo icons contribute to the core value of the product being sold/shared, you will need an Extended License. 47 | 48 | By purchasing an Extended License, you’re also granted the right to: 49 | 50 | - Use up to 500 icons in a single project (the one you’re purchasing the Extended License for) if the users/customers can access Nucleo source files (e.g. Nucleo icons are stored in a folder inside the downloadable file). 51 | - Use unlimited icons if the users/customers cannot access Nucleo source files (e.g. Nucleo icons are encrypted and user can only use icons throughout the application). 52 | 53 | The downloadable source file has to include [Nucleo Standard License](https://github.com/NucleoApp/license-standard), as well as Nucleo Extended License. 54 | 55 | Example of products offered for sale (or for free) where Nucleo contributes to the core value of the product being sold/shared: 56 | 57 | - Logo builder application that combines Nucleo icons to create a logo 58 | - Theme builder where users can browse Nucleo icons and pick the ones to include in their design. 59 | - Application used to create presentations, where users can pick Nucleo icons through the built-in presentation builder. 60 | 61 | If you’re still unclear about what is or isn’t allowed under this license, please contact us at info@nucleoapp.com. 62 | -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.eot -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.ttf -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.woff -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/fonts/nucleo-outline.woff2 -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/apple-icon.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/avatar.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg1.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg11.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg3.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg4.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg5.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg6.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg7.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/bg8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/bg8.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/blurred-image-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/blurred-image-1.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/creative-tim-white-slim2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/creative-tim-white-slim2.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/default-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/default-avatar.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/eva.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/eva.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/favicon.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/AD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/AD.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/AE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/AE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/AG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/AG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/AM.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/AR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/AR.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/AT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/AT.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/AU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/AU.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/BE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/BE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/BF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/BF.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/BG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/BG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/BO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/BO.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/BR.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CD.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CH.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CL.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CM.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CN.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CO.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/CZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/CZ.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/DE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/DE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/DJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/DJ.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/DK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/DK.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/DZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/DZ.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/EE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/EE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/EG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/EG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/ES.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/ES.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/FI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/FI.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/FR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/FR.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/GA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/GA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/GB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/GB.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/GM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/GM.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/GT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/GT.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/HN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/HN.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/HT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/HT.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/HU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/HU.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/ID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/ID.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/IE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/IE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/IL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/IL.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/IN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/IN.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/IQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/IQ.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/IR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/IR.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/IT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/IT.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/JM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/JM.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/JO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/JO.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/JP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/JP.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/KG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/KG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/KN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/KN.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/KP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/KP.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/KR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/KR.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/KW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/KW.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/KZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/KZ.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/LA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/LA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/LB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/LB.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/LC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/LC.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/LS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/LS.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/LU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/LU.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/LV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/LV.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/MG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/MG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/MK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/MK.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/ML.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/ML.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/MM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/MM.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/MT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/MT.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/MX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/MX.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/NA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/NA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/NE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/NE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/NG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/NG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/NI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/NI.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/NL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/NL.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/NO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/NO.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/OM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/OM.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/PA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/PA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/PE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/PE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/PG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/PG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/PK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/PK.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/PL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/PL.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/PT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/PT.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/PY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/PY.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/QA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/QA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/RO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/RO.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/RU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/RU.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/RW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/RW.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/SA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/SA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/SE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/SE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/SG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/SG.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/SL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/SL.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/SN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/SN.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/SO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/SO.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/SV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/SV.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/TD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/TD.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/TJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/TJ.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/TL.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/TR.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/TZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/TZ.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/UA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/UA.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/US.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/VE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/VE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/VN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/VN.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/flags/YE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/flags/YE.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/header.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/hero-image-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/hero-image-1.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/hero-image-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/hero-image-2.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/hero-image-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/hero-image-3.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/invision-white-slim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/invision-white-slim.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/julie.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/julie.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/landing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/landing.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/login.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/logo-square.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/logo-square.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/logo.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/now-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/now-logo.png -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/nucleo-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 11 | 15 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/profile.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/img/ryan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LookBackInTheRain/oauth-boot/7bf6a0700947e555e12454f0ec59bbcf017de0de/src/main/resources/statics/libs/now-ui/img/ryan.jpg -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/js/now-ui-kit.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["_site_kit_free/assets/js/kit-free.js"],"names":["big_image","navbar_initialized","nowuiKit","$navbar","scroll_distance","oVal","transparent","transparentDemo","fixedTop","backgroundOrange","toggle_initialized","debounce","func","wait","immediate","timeout","context","this","args","arguments","clearTimeout","setTimeout","apply","$","document","ready","tooltip","each","color_class","data","popover","template","initNavbarImage","attr","length","checkScrollForTransparentNavbar","window","on","parent","addClass","removeClass","$this","data_on_label","data_off_label","bootstrapSwitch","onText","offText","width","nowuiKitDemo","checkScrollForParallax","carousel","interval","datepicker","templates","leftArrow","rightArrow","datepicker_color","scrollTop","css","transform","-webkit-transform","-ms-transform","-o-transform","$toggle","misc","navbar_menu_visible","remove","div","appendTo","click","find","siblings","background_image","undefined","hasClass","removeAttr","initSliders","slider","getElementById","noUiSlider","create","start","connect","range","min","max","slider2"],"mappings":"AAkBA,IACIA,UAKAC,mBAIAC,SACJC,QACAC,gBACAC,KAbIC,aAAc,EAGdC,iBAAkB,EAClBC,UAAW,EAGXC,kBAAmB,EACnBC,oBAAqB,EAwGzB,SAASC,SAASC,EAAMC,EAAMC,GAC7B,IAAIC,EACJ,OAAO,WACN,IAAIC,EAAUC,KAAMC,EAAOC,UAC3BC,aAAaL,GACbA,EAAUM,WAAW,WACpBN,EAAU,KACLD,GAAWF,EAAKU,MAAMN,EAASE,IAClCL,GACCC,IAAcC,GAASH,EAAKU,MAAMN,EAASE,IA2HjD,SAASP,SAASC,EAAMC,EAAMC,GAC7B,IAAIC,EACJ,OAAO,WACN,IAAIC,EAAUC,KAAMC,EAAOC,UAC3BC,aAAaL,GACbA,EAAUM,WAAW,WACpBN,EAAU,KACLD,GAAWF,EAAKU,MAAMN,EAASE,IAClCL,GACCC,IAAcC,GAASH,EAAKU,MAAMN,EAASE,IA9OjDK,EAAEC,UAAUC,MAAM,WAEdF,EAAE,4CAA4CG,UAG9CH,EAAE,2BAA2BI,KAAK,WAC9BC,YAAcL,EAAEN,MAAMY,KAAK,SAC3BN,EAAEN,MAAMa,QAAQ,CACZC,SAAU,+BAA+BH,YAAa,uHAK9D1B,SAAS8B,kBAET7B,QAAUoB,EAAE,4BACZnB,gBAAkBD,QAAQ8B,KAAK,oBAAsB,IAIV,GAAxCV,EAAE,4BAA4BW,SAC7BhC,SAASiC,kCACTZ,EAAEa,QAAQC,GAAG,SAAUnC,SAASiC,kCAGpCZ,EAAE,iBAAiBc,GAAG,QAAS,WAC3Bd,EAAEN,MAAMqB,OAAO,gBAAgBC,SAAS,uBACzCF,GAAG,OAAQ,WACVd,EAAEN,MAAMqB,OAAO,gBAAgBE,YAAY,uBAI/CjB,EAAE,qBAAqBI,KAAK,WACxBc,MAAQlB,EAAEN,MACVyB,cAAgBD,MAAMZ,KAAK,aAAe,GAC1Cc,eAAiBF,MAAMZ,KAAK,cAAgB,GAE5CY,MAAMG,gBAAgB,CAClBC,OAAQH,cACRI,QAASH,mBAIQ,KAArBpB,EAAEa,QAAQW,UACV/C,UAAYuB,EAAE,4CAEdA,EAAEa,QAAQC,GAAG,SAAUW,aAAaC,yBAI3C1B,EAAE,aAAa2B,SAAS,CACjBC,SAAU,MAGd5B,EAAE,gBAAgBI,KAAK,WACnBJ,EAAEN,MAAMmC,WAAW,CACfC,UAAU,CACNC,UAAW,qDACXC,WAAY,yDAEjBlB,GAAG,OAAQ,WACNd,EAAE,eAAegB,SAAS,QAE1BiB,iBAAmBjC,EAAEN,MAAMY,KAAK,oBACD,GAA3B2B,iBAAiBtB,QACjBX,EAAE,eAAegB,SAAS,cAAeiB,oBAE9CnB,GAAG,OAAQ,WACVd,EAAE,eAAeiB,YAAY,cAQ7CQ,aAAe,CACXC,uBAAwBtC,SAAS,WACRY,EAAEN,MAAMwC,YAE7BpD,KAAQkB,EAAEa,QAAQqB,YAAc,EAChCzD,UAAU0D,IAAI,CACVC,UAAY,iBAAmBtD,KAAM,QACrCuD,oBAAoB,iBAAmBvD,KAAM,QAC7CwD,gBAAgB,iBAAmBxD,KAAM,QACzCyD,eAAe,iBAAmBzD,KAAM,WAG7C,IAsBPkB,EAAEa,QAAQC,GAAG,SAAU,WACnBnC,SAAS8B,oBAGbT,EAAEC,UAAUa,GAAG,QAAS,kBAAmB,WACvC0B,QAAUxC,EAAEN,MAE4B,GAArCf,SAAS8D,KAAKC,qBACb1C,EAAE,QAAQiB,YAAY,YACvBtC,SAAS8D,KAAKC,oBAAsB,EACnC1C,EAAE,cAAc2C,SAChB7C,WAAW,WACR0C,QAAQvB,YAAY,YACrB,OAEHnB,WAAW,WACP0C,QAAQxB,SAAS,YAClB,KACH4B,IAAM,6BACN5C,EAAE4C,KAAKC,SAAS,QAAQC,MAAM,WAC1B9C,EAAE,QAAQiB,YAAY,YACtBtC,SAAS8D,KAAKC,oBAAsB,EACnC5C,WAAW,WACR0C,QAAQvB,YAAY,WACpBjB,EAAE,cAAc2C,UAChB,OAGT3C,EAAE,QAAQgB,SAAS,YAClBrC,SAAS8D,KAAKC,oBAAsB,KAI3C/D,SAAW,CACP8D,KAAK,CACDC,oBAAqB,GAGzB9B,gCAAiCxB,SAAS,WAC/BY,EAAEC,UAAUiC,YAAcrD,gBACtBE,cACCA,aAAc,EACdiB,EAAE,4BAA4BiB,YAAY,uBAGzClC,cACDA,aAAc,EACdiB,EAAE,4BAA4BgB,SAAS,wBAGpD,IAEHP,gBAAiB,WACb,IAAI7B,EAAUoB,EAAE,WAAW+C,KAAK,qBAAqBC,SAAS,oBAC1DC,EAAmBrE,EAAQ0B,KAAK,aAEb4C,MAApBD,IACGjD,EAAEa,QAAQW,QAAU,KAAOxB,EAAE,QAAQmD,SAAS,eAChDvE,EAAQuD,IAAI,aAAa,QAAUc,EAAmB,MAC9CG,WAAW,kBACXjB,IAAI,kBAAkB,SACtBnB,SAAS,aAEjBpC,EAAQuD,IAAI,aAAa,IACjBzB,KAAK,iBAAkB,GAAIuC,GAC3Bd,IAAI,kBAAkB,IACtBlB,YAAY,eAK5BoC,YAAa,WAET,IAAIC,EAASrD,SAASsD,eAAe,iBAErCC,WAAWC,OAAOH,EAAQ,CACtBI,MAAO,GACPC,QAAS,EAAC,GAAK,GACfC,MAAO,CACHC,IAAK,EACLC,IAAK,OAIb,IAAIC,EAAU9D,SAASsD,eAAe,gBAEtCC,WAAWC,OAAOM,EAAS,CACvBL,MAAO,CAAE,GAAI,IACbC,SAAS,EACTC,MAAO,CACHC,IAAM,EACNC,IAAM,SAOtBrC,aAAe,CACXC,uBAAwBtC,SAAS,WACRY,EAAEN,MAAMwC,YAE7BpD,KAAQkB,EAAEa,QAAQqB,YAAc,EAChCzD,UAAU0D,IAAI,CACVC,UAAY,iBAAmBtD,KAAM,QACrCuD,oBAAoB,iBAAmBvD,KAAM,QAC7CwD,gBAAgB,iBAAmBxD,KAAM,QACzCyD,eAAe,iBAAmBzD,KAAM,WAG7C"} -------------------------------------------------------------------------------- /src/main/resources/statics/libs/now-ui/js/now-ui-kit.min.js: -------------------------------------------------------------------------------- 1 | // ========================================================= 2 | // * Now UI Kit - v1.3.0 3 | // ========================================================= 4 | // 5 | // * Product Page: https://www.creative-tim.com/product/now-ui-kit 6 | // * Copyright 2019 Creative Tim (http://www.creative-tim.com) 7 | // * Licensed under MIT (https://github.com/creativetimofficial/now-ui-kit/blob/master/LICENSE.md) 8 | // 9 | // * Designed by www.invisionapp.com Coded by www.creative-tim.com 10 | // 11 | // ========================================================= 12 | // 13 | // * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | 15 | var big_image,navbar_initialized,nowuiKit,$navbar,scroll_distance,oVal,transparent=!0,transparentDemo=!0,fixedTop=!1,backgroundOrange=!1,toggle_initialized=!1;function debounce(n,e,t){var r;return function(){var a=this,o=arguments;clearTimeout(r),r=setTimeout(function(){r=null,t||n.apply(a,o)},e),t&&!r&&n.apply(a,o)}}function debounce(n,e,t){var r;return function(){var a=this,o=arguments;clearTimeout(r),r=setTimeout(function(){r=null,t||n.apply(a,o)},e),t&&!r&&n.apply(a,o)}}$(document).ready(function(){$('[data-toggle="tooltip"], [rel="tooltip"]').tooltip(),$('[data-toggle="popover"]').each(function(){color_class=$(this).data("color"),$(this).popover({template:'

'})}),nowuiKit.initNavbarImage(),$navbar=$(".navbar[color-on-scroll]"),scroll_distance=$navbar.attr("color-on-scroll")||500,0!=$(".navbar[color-on-scroll]").length&&(nowuiKit.checkScrollForTransparentNavbar(),$(window).on("scroll",nowuiKit.checkScrollForTransparentNavbar)),$(".form-control").on("focus",function(){$(this).parent(".input-group").addClass("input-group-focus")}).on("blur",function(){$(this).parent(".input-group").removeClass("input-group-focus")}),$(".bootstrap-switch").each(function(){$this=$(this),data_on_label=$this.data("on-label")||"",data_off_label=$this.data("off-label")||"",$this.bootstrapSwitch({onText:data_on_label,offText:data_off_label})}),992<=$(window).width()&&(big_image=$('.page-header-image[data-parallax="true"]'),$(window).on("scroll",nowuiKitDemo.checkScrollForParallax)),$(".carousel").carousel({interval:4e3}),$(".date-picker").each(function(){$(this).datepicker({templates:{leftArrow:'',rightArrow:''}}).on("show",function(){$(".datepicker").addClass("open"),datepicker_color=$(this).data("datepicker-color"),0!=datepicker_color.length&&$(".datepicker").addClass("datepicker-"+datepicker_color)}).on("hide",function(){$(".datepicker").removeClass("open")})})}),nowuiKitDemo={checkScrollForParallax:debounce(function(){$(this).scrollTop();oVal=$(window).scrollTop()/3,big_image.css({transform:"translate3d(0,"+oVal+"px,0)","-webkit-transform":"translate3d(0,"+oVal+"px,0)","-ms-transform":"translate3d(0,"+oVal+"px,0)","-o-transform":"translate3d(0,"+oVal+"px,0)"})},6)},$(window).on("resize",function(){nowuiKit.initNavbarImage()}),$(document).on("click",".navbar-toggler",function(){$toggle=$(this),1==nowuiKit.misc.navbar_menu_visible?($("html").removeClass("nav-open"),nowuiKit.misc.navbar_menu_visible=0,$("#bodyClick").remove(),setTimeout(function(){$toggle.removeClass("toggled")},550)):(setTimeout(function(){$toggle.addClass("toggled")},580),div='
',$(div).appendTo("body").click(function(){$("html").removeClass("nav-open"),nowuiKit.misc.navbar_menu_visible=0,setTimeout(function(){$toggle.removeClass("toggled"),$("#bodyClick").remove()},550)}),$("html").addClass("nav-open"),nowuiKit.misc.navbar_menu_visible=1)}),nowuiKit={misc:{navbar_menu_visible:0},checkScrollForTransparentNavbar:debounce(function(){$(document).scrollTop()>scroll_distance?transparent&&(transparent=!1,$(".navbar[color-on-scroll]").removeClass("navbar-transparent")):transparent||(transparent=!0,$(".navbar[color-on-scroll]").addClass("navbar-transparent"))},17),initNavbarImage:function(){var a=$(".navbar").find(".navbar-translate").siblings(".navbar-collapse"),o=a.data("nav-image");null!=o&&($(window).width()<991||$("body").hasClass("burger-menu")?a.css("background","url('"+o+"')").removeAttr("data-nav-image").css("background-size","cover").addClass("has-image"):a.css("background","").attr("data-nav-image",""+o).css("background-size","").removeClass("has-image"))},initSliders:function(){var a=document.getElementById("sliderRegular");noUiSlider.create(a,{start:40,connect:[!0,!1],range:{min:0,max:100}});var o=document.getElementById("sliderDouble");noUiSlider.create(o,{start:[20,60],connect:!0,range:{min:0,max:100}})}},nowuiKitDemo={checkScrollForParallax:debounce(function(){$(this).scrollTop();oVal=$(window).scrollTop()/3,big_image.css({transform:"translate3d(0,"+oVal+"px,0)","-webkit-transform":"translate3d(0,"+oVal+"px,0)","-ms-transform":"translate3d(0,"+oVal+"px,0)","-o-transform":"translate3d(0,"+oVal+"px,0)"})},6)}; 16 | -------------------------------------------------------------------------------- /src/main/resources/statics/styles/base-grant.css: -------------------------------------------------------------------------------- 1 | .header { 2 | text-align: center; 3 | margin: 0; 4 | padding: 2rem; 5 | background-color: #E9ECEF; 6 | height: 6rem; 7 | line-height: 2rem; 8 | font-size: 1.5rem; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/resources/statics/styles/base-login.css: -------------------------------------------------------------------------------- 1 | 2 | .card-container { 3 | padding: 0 10rem; 4 | } 5 | .header-title { 6 | text-align: center; 7 | margin: 0; 8 | padding: 2rem; 9 | background-color: #E9ECEF; 10 | height: 8rem; 11 | line-height: 4rem; 12 | border-bottom-right-radius: 20rem; 13 | border-top-left-radius: 20rem; 14 | } 15 | 16 | .header-title .name { 17 | color: #11CDEF; 18 | } 19 | 20 | .header-title .separator { 21 | color: #888888; 22 | } 23 | .header-title .type { 24 | color: #888888; 25 | } 26 | 27 | .content { 28 | padding: 0 3rem; 29 | } 30 | 31 | .footer { 32 | text-align: center; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/resources/statics/styles/base.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #E9ECEF; 3 | font-size: 18px !important; 4 | } 5 | input { 6 | height: 2.5rem !important; 7 | background-color: white !important; 8 | } 9 | .btn { 10 | margin: 0 !important; 11 | } 12 | .form-control { 13 | border-radius: 0.3rem !important; 14 | } 15 | 16 | .input-group-append { 17 | margin-left: -6px !important; 18 | } 19 | 20 | .form-group .input-group-prepend, .input-group .input-group-prepend { 21 | margin-right: -6px; 22 | } 23 | 24 | .input-group-prepend { 25 | margin-right: -6px; 26 | } 27 | .input-group-prepend .input-group-text { 28 | border-radius: 0.3rem 0 0 0.3rem; 29 | z-index: 100; 30 | } 31 | 32 | 33 | .input-group-append .input-group-text { 34 | border-radius: 0 0.3rem 0.3rem 0; 35 | z-index: 100; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/views/base-grant.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAUTH·BOOT 授权 6 | 7 | 8 | 9 | 10 | 33 |
34 |
35 |
36 |

确认授权

37 |
38 |
39 |
40 |
41 | 42 | 请求授权,该应用将获取你的以下信息 43 |
44 |

昵称,性别,头像

45 | 授权后表明你已同意 OAUTH-BOOT 服务协议 46 |
47 | 48 | 49 | 50 | 51 |
52 | 53 |
54 |
55 | 56 | 57 |
58 |
59 |
60 |
61 | 62 |
63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/main/resources/views/commons/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAUTH-BOOT 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test/java/Main.java: -------------------------------------------------------------------------------- 1 | import org.springframework.boot.autoconfigure.cache.CacheProperties; 2 | import org.springframework.boot.autoconfigure.data.redis.RedisProperties; 3 | import org.springframework.security.core.parameters.P; 4 | import org.springframework.util.AntPathMatcher; 5 | 6 | import java.io.*; 7 | import java.util.LinkedList; 8 | import java.util.Queue; 9 | 10 | /** 11 | * @author yuit 12 | * @create 2018/10/22 17:38 13 | * @description 14 | * @modify 15 | */ 16 | public class Main { 17 | 18 | 19 | 20 | public static void main(String[] args) throws InterruptedException { 21 | Queue res = new LinkedList<>(); 22 | Producer p = new Producer(res); 23 | Consumer c = new Consumer(res); 24 | 25 | Thread pth = new Thread(p); 26 | Thread cth = new Thread(c); 27 | 28 | pth.start(); 29 | cth.start(); 30 | 31 | pth.join(); 32 | cth.join(); 33 | 34 | } 35 | 36 | 37 | } 38 | 39 | class Producer implements Runnable { 40 | 41 | private Queue res; 42 | 43 | public Producer(Queue res) { 44 | this.res = res; 45 | } 46 | 47 | @Override 48 | public void run() { 49 | 50 | synchronized (res){ 51 | if (res.size()>=5) { 52 | res.notify(); 53 | try { 54 | res.wait(); 55 | } catch (InterruptedException e) { 56 | e.printStackTrace(); 57 | } 58 | } 59 | 60 | res.add(1); 61 | res.notify(); 62 | try { 63 | Thread.sleep(1*1000); 64 | } catch (InterruptedException e) { 65 | e.printStackTrace(); 66 | } 67 | 68 | System.out.println("Producer: "+ res); 69 | 70 | run(); 71 | } 72 | 73 | } 74 | } 75 | 76 | 77 | class Consumer implements Runnable { 78 | private Queue res; 79 | 80 | public Consumer(Queue res) { 81 | this.res = res; 82 | } 83 | 84 | @Override 85 | public void run() { 86 | synchronized (res){ 87 | if (res.size()==0) { 88 | res.notify(); 89 | try { 90 | res.wait(); 91 | } catch (InterruptedException e) { 92 | e.printStackTrace(); 93 | } 94 | } 95 | res.poll(); 96 | res.notify(); 97 | try { 98 | Thread.sleep(1*1000); 99 | } catch (InterruptedException e) { 100 | e.printStackTrace(); 101 | } 102 | 103 | System.out.println("Consumer: "+ res); 104 | 105 | run(); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/test/java/club/yuit/oauth/boot/BootApplicationTests.java: -------------------------------------------------------------------------------- 1 | package club.yuit.oauth.boot; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.test.context.SpringBootTest; 7 | import org.springframework.security.crypto.password.PasswordEncoder; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | @RunWith(SpringRunner.class) 11 | @SpringBootTest 12 | public class BootApplicationTests { 13 | 14 | @Autowired 15 | private PasswordEncoder passwordEncoder; 16 | 17 | @Test 18 | public void contextLoads() { 19 | String p="$2a$10$M2WyFkyD0zgIOyDZ6rCaG.804xZfYnQ0BWc1fK5ajK.KtkYfyT7.u"; 20 | System.out.println(passwordEncoder.matches("123qwe",p)); 21 | 22 | 23 | } 24 | 25 | } 26 | --------------------------------------------------------------------------------