├── .gitignore ├── Code-common ├── build.gradle ├── out │ └── production │ │ └── classes │ │ └── com │ │ └── tw │ │ └── common │ │ └── utils │ │ ├── NetworkUtils.class │ │ └── StringUtils.class └── src │ └── main │ └── java │ └── com │ └── tw │ └── common │ └── utils │ ├── NetworkUtils.java │ └── StringUtils.java ├── Code ├── build.gradle └── src │ └── main │ ├── java │ └── com │ │ └── tw │ │ └── cloud │ │ ├── CommentGenerator.java │ │ ├── Generator.java │ │ ├── SpringFlutterApplication.java │ │ ├── bean │ │ ├── CommonResp.java │ │ ├── UmsGallery.java │ │ ├── UmsGalleryExample.java │ │ ├── User.java │ │ ├── UserExample.java │ │ ├── request │ │ │ ├── AuthenticationRequest.java │ │ │ └── CommonRequest.java │ │ └── user │ │ │ ├── CustomerInfoReply.java │ │ │ └── JwtUserDetail.java │ │ ├── component │ │ ├── JwtAuthenticationTokenFilter.java │ │ ├── RestAuthenticationEntryPoint.java │ │ └── RestfulAccessDeniedHandler.java │ │ ├── config │ │ ├── MyBatisConfig.java │ │ └── WebSecurityConfig.java │ │ ├── controller │ │ ├── UmsController.java │ │ └── UserController.java │ │ ├── mapper │ │ ├── UmsGalleryMapper.java │ │ └── UserMapper.java │ │ ├── service │ │ ├── RedisService.java │ │ ├── UmsService.java │ │ ├── UserService.java │ │ └── impl │ │ │ ├── RedisServiceImpl.java │ │ │ ├── UmsServiceIml.java │ │ │ ├── UserDetailServiceImpl.java │ │ │ └── UserServiceImpl.java │ │ └── utils │ │ ├── Constants.java │ │ ├── ErrorCode.java │ │ ├── IErrorCode.java │ │ ├── JwtTokenUtil.java │ │ ├── ResultCode.java │ │ └── UnifyApiUri.java │ └── resources │ ├── application.yml │ ├── generator.properties │ ├── generatorConfig.xml │ ├── mapper │ ├── UmsGalleryMapper.xml │ └── UserMapper.xml │ └── mybatis-config.xml ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── image_getCustomerInfo.png ├── image_login.png └── user_table.jpg └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .gradle/ 3 | Code/out/ 4 | Code/Code.iml 5 | .idea/workspace.xml 6 | Code/.DS_Store -------------------------------------------------------------------------------- /Code-common/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | 6 | 7 | sourceCompatibility = 1.8 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | testCompile group: 'junit', name: 'junit', version: '4.12' 15 | } 16 | -------------------------------------------------------------------------------- /Code-common/out/production/classes/com/tw/common/utils/NetworkUtils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenmengzhuifeng/SpringFlutter/52baa9da26ef90ee436d11d017ecd829809f2d8b/Code-common/out/production/classes/com/tw/common/utils/NetworkUtils.class -------------------------------------------------------------------------------- /Code-common/out/production/classes/com/tw/common/utils/StringUtils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenmengzhuifeng/SpringFlutter/52baa9da26ef90ee436d11d017ecd829809f2d8b/Code-common/out/production/classes/com/tw/common/utils/StringUtils.class -------------------------------------------------------------------------------- /Code-common/src/main/java/com/tw/common/utils/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package com.tw.common.utils; 2 | 3 | import java.net.Inet4Address; 4 | import java.net.InetAddress; 5 | import java.net.NetworkInterface; 6 | import java.net.UnknownHostException; 7 | import java.util.Enumeration; 8 | import java.util.logging.Logger; 9 | 10 | /** 11 | * 网络相关方法 12 | * 13 | * @author 14 | * @create 2020-02-05 9:18 PM 15 | **/ 16 | public class NetworkUtils { 17 | 18 | 19 | public static String getLocalHost(){ 20 | 21 | try { 22 | Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); 23 | InetAddress ip = null; 24 | while (allNetInterfaces.hasMoreElements()) { 25 | NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement(); 26 | if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) { 27 | continue; 28 | } else { 29 | Enumeration addresses = netInterface.getInetAddresses(); 30 | while (addresses.hasMoreElements()) { 31 | ip = addresses.nextElement(); 32 | if (ip != null && ip instanceof Inet4Address) { 33 | return ip.getHostAddress(); 34 | } 35 | } 36 | } 37 | } 38 | } catch (Exception e) { 39 | System.err.println("IP地址获取失败" + e.toString()); 40 | } 41 | return ""; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Code-common/src/main/java/com/tw/common/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.tw.common.utils; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * 字符串相关方法类 7 | * 8 | * @author 9 | * @create 2020-01-31 12:41 PM 10 | **/ 11 | public class StringUtils { 12 | 13 | 14 | /** 15 | * 生成6位随机码 16 | * @return 17 | */ 18 | public static String randomCode() { 19 | StringBuilder str = new StringBuilder(); 20 | Random random = new Random(); 21 | for (int i = 0; i < 6; i++) { 22 | str.append(random.nextInt(10)); 23 | } 24 | return str.toString(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Code/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | apply plugin: 'eclipse' 3 | apply plugin: 'idea' 4 | apply plugin: 'spring-boot' 5 | sourceCompatibility = 1.8 6 | targetCompatibility = 1.8 7 | compileJava.dependsOn(processResources) 8 | jar { 9 | baseName = 'springflutterserver' 10 | version = '0.1.0' 11 | } 12 | 13 | dependencies { 14 | testCompile group: 'junit', name: 'junit', version: '4.12' 15 | compile('org.springframework.boot:spring-boot-starter-web') 16 | compile('org.springframework.boot:spring-boot-starter-jdbc') 17 | compile('com.alibaba:druid-spring-boot-starter:1.1.10') 18 | compile("org.springframework.boot:spring-boot-starter-security") 19 | compile("org.springframework.security.oauth:spring-security-oauth2") 20 | compile("org.springframework.security:spring-security-jwt") 21 | compile("org.springframework.boot:spring-boot-starter-data-redis") 22 | compile("mysql:mysql-connector-java") 23 | compile('io.jsonwebtoken:jjwt:0.9.0') 24 | compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1') 25 | compile('mysql:mysql-connector-java:8.0.11') 26 | compile('cn.hutool:hutool-all:4.5.7') 27 | compile('org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2') 28 | compile project(':Code-common') 29 | } 30 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/CommentGenerator.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud; 2 | 3 | import org.mybatis.generator.api.IntrospectedColumn; 4 | import org.mybatis.generator.api.IntrospectedTable; 5 | import org.mybatis.generator.api.dom.java.CompilationUnit; 6 | import org.mybatis.generator.api.dom.java.Field; 7 | import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType; 8 | import org.mybatis.generator.internal.DefaultCommentGenerator; 9 | import org.mybatis.generator.internal.util.StringUtility; 10 | 11 | import java.util.Properties; 12 | 13 | /** 14 | * 自定义注释生成器 15 | * Created by macro on 2018/4/26. 16 | */ 17 | public class CommentGenerator extends DefaultCommentGenerator { 18 | private boolean addRemarkComments = false; 19 | private static final String EXAMPLE_SUFFIX="Example"; 20 | private static final String API_MODEL_PROPERTY_FULL_CLASS_NAME="io.swagger.annotations.ApiModelProperty"; 21 | 22 | /** 23 | * 设置用户配置的参数 24 | */ 25 | @Override 26 | public void addConfigurationProperties(Properties properties) { 27 | super.addConfigurationProperties(properties); 28 | this.addRemarkComments = StringUtility.isTrue(properties.getProperty("addRemarkComments")); 29 | } 30 | 31 | /** 32 | * 给字段添加注释 33 | */ 34 | @Override 35 | public void addFieldComment(Field field, IntrospectedTable introspectedTable, 36 | IntrospectedColumn introspectedColumn) { 37 | String remarks = introspectedColumn.getRemarks(); 38 | //根据参数和备注信息判断是否添加备注信息 39 | if(addRemarkComments&& StringUtility.stringHasValue(remarks)){ 40 | // addFieldJavaDoc(field, remarks); 41 | //数据库中特殊字符需要转义 42 | if(remarks.contains("\"")){ 43 | remarks = remarks.replace("\"","'"); 44 | } 45 | //给model的字段添加swagger注解 46 | field.addJavaDocLine("@ApiModelProperty(value = \""+remarks+"\")"); 47 | } 48 | } 49 | 50 | /** 51 | * 给model的字段添加注释 52 | */ 53 | private void addFieldJavaDoc(Field field, String remarks) { 54 | //文档注释开始 55 | field.addJavaDocLine("/**"); 56 | //获取数据库字段的备注信息 57 | String[] remarkLines = remarks.split(System.getProperty("line.separator")); 58 | for(String remarkLine:remarkLines){ 59 | field.addJavaDocLine(" * "+remarkLine); 60 | } 61 | addJavadocTag(field, false); 62 | field.addJavaDocLine(" */"); 63 | } 64 | 65 | @Override 66 | public void addJavaFileComment(CompilationUnit compilationUnit) { 67 | super.addJavaFileComment(compilationUnit); 68 | //只在model中添加swagger注解类的导入 69 | if(!compilationUnit.isJavaInterface()&&!compilationUnit.getType().getFullyQualifiedName().contains(EXAMPLE_SUFFIX)){ 70 | compilationUnit.addImportedType(new FullyQualifiedJavaType(API_MODEL_PROPERTY_FULL_CLASS_NAME)); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/Generator.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud; 2 | 3 | import org.mybatis.generator.api.MyBatisGenerator; 4 | import org.mybatis.generator.config.Configuration; 5 | import org.mybatis.generator.config.xml.ConfigurationParser; 6 | import org.mybatis.generator.internal.DefaultShellCallback; 7 | 8 | import java.io.InputStream; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | /** 13 | * 用于生产MBG的代码 14 | * Created by macro on 2018/4/26. 15 | */ 16 | public class Generator { 17 | public static void main(String[] args) throws Exception { 18 | //MBG 执行过程中的警告信息 19 | List warnings = new ArrayList(); 20 | //当生成的代码重复时,覆盖原代码 21 | boolean overwrite = true; 22 | //读取我们的 MBG 配置文件 23 | InputStream is = Generator.class.getResourceAsStream("/generatorConfig.xml"); 24 | ConfigurationParser cp = new ConfigurationParser(warnings); 25 | Configuration config = cp.parseConfiguration(is); 26 | is.close(); 27 | 28 | DefaultShellCallback callback = new DefaultShellCallback(overwrite); 29 | //创建 MBG 30 | MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); 31 | //执行生成代码 32 | myBatisGenerator.generate(null); 33 | //输出警告信息 34 | for (String warning : warnings) { 35 | System.out.println(warning); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/SpringFlutterApplication.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud; 2 | 3 | import org.apache.coyote.http11.AbstractHttp11Protocol; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; 8 | import org.springframework.context.annotation.Bean; 9 | 10 | @SpringBootApplication 11 | public class SpringFlutterApplication { 12 | 13 | public static void main(String[] args) { 14 | SpringApplication.run(SpringFlutterApplication.class, args); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/CommonResp.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean; 2 | 3 | 4 | import com.tw.cloud.utils.Constants; 5 | import com.tw.cloud.utils.ResultCode; 6 | 7 | /** 8 | * 公共的接口返回bean 9 | * 10 | * @param 11 | */ 12 | public class CommonResp { 13 | 14 | 15 | private int resultCode; 16 | 17 | private String errorCode; 18 | 19 | private String errorMsg; 20 | 21 | private T response; 22 | 23 | public CommonResp(int resultCode, String errorCode, String errorMsg, T response) { 24 | this.resultCode = resultCode; 25 | this.errorCode = errorCode; 26 | this.errorMsg = errorMsg; 27 | this.response = response; 28 | } 29 | 30 | /** 31 | * 成功返回结果 32 | * 33 | * @param data 获取的数据 34 | */ 35 | public static CommonResp success(T data) { 36 | return new CommonResp(Constants.RESULT_OK,"","", data); 37 | } 38 | 39 | /** 40 | * 成功返回结果 41 | * 42 | * @param data 获取的数据 43 | * @param message 提示信息 44 | */ 45 | public static CommonResp success(T data, String message) { 46 | return new CommonResp(Constants.RESULT_OK,"", message, data); 47 | } 48 | 49 | /** 50 | * 失败返回结果 51 | * @param errorCode 错误码 52 | */ 53 | public static CommonResp failed(ResultCode errorCode) { 54 | return new CommonResp(Constants.RESULT_OK,errorCode.getCode(), errorCode.getMessage(), null); 55 | } 56 | 57 | /** 58 | * 失败返回结果 59 | * @param message 提示信息 60 | */ 61 | public static CommonResp failed(String message) { 62 | return new CommonResp(Constants.RESULT_ERROR,ResultCode.RESULT_CODE_1002.getCode(), message, null); 63 | } 64 | 65 | /** 66 | * 失败返回结果 67 | */ 68 | public static CommonResp failed() { 69 | return failed(ResultCode.RESULT_CODE_1002); 70 | } 71 | 72 | /** 73 | * 参数验证失败返回结果 74 | */ 75 | public static CommonResp validateFailed() { 76 | return failed(ResultCode.RESULT_CODE_1003); 77 | } 78 | 79 | /** 80 | * 参数验证失败返回结果 81 | * @param message 提示信息 82 | */ 83 | public static CommonResp validateFailed(String message) { 84 | return new CommonResp(Constants.RESULT_ERROR,ResultCode.RESULT_CODE_1003.getCode(), message, null); 85 | } 86 | 87 | /** 88 | * 未登录返回结果 89 | */ 90 | public static CommonResp unauthorized(T data) { 91 | return new CommonResp(Constants.RESULT_ERROR,ResultCode.RESULT_CODE_1004.getCode(), ResultCode.RESULT_CODE_1004.getMessage(), data); 92 | } 93 | 94 | /** 95 | * 未授权返回结果 96 | */ 97 | public static CommonResp forbidden(T data) { 98 | return new CommonResp(Constants.RESULT_ERROR,ResultCode.RESULT_CODE_1005.getCode(), ResultCode.RESULT_CODE_1005.getMessage(), data); 99 | } 100 | 101 | public int getResultCode() { 102 | return resultCode; 103 | } 104 | 105 | public void setResultCode(int resultCode) { 106 | this.resultCode = resultCode; 107 | } 108 | 109 | public String getErrorCode() { 110 | return errorCode; 111 | } 112 | 113 | public void setErrorCode(String errorCode) { 114 | this.errorCode = errorCode; 115 | } 116 | 117 | public String getErrorMsg() { 118 | return errorMsg; 119 | } 120 | 121 | public void setErrorMsg(String errorMsg) { 122 | this.errorMsg = errorMsg; 123 | } 124 | 125 | public T getResponse() { 126 | return response; 127 | } 128 | 129 | public void setResponse(T response) { 130 | this.response = response; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/UmsGallery.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | public class UmsGallery implements Serializable { 7 | private Integer id; 8 | 9 | private Integer userId; 10 | 11 | private String name; 12 | 13 | private String url; 14 | 15 | private Date createTime; 16 | 17 | private String description; 18 | 19 | private static final long serialVersionUID = 1L; 20 | 21 | public Integer getId() { 22 | return id; 23 | } 24 | 25 | public void setId(Integer id) { 26 | this.id = id; 27 | } 28 | 29 | public Integer getUserId() { 30 | return userId; 31 | } 32 | 33 | public void setUserId(Integer userId) { 34 | this.userId = userId; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public String getUrl() { 46 | return url; 47 | } 48 | 49 | public void setUrl(String url) { 50 | this.url = url; 51 | } 52 | 53 | public Date getCreateTime() { 54 | return createTime; 55 | } 56 | 57 | public void setCreateTime(Date createTime) { 58 | this.createTime = createTime; 59 | } 60 | 61 | public String getDescription() { 62 | return description; 63 | } 64 | 65 | public void setDescription(String description) { 66 | this.description = description; 67 | } 68 | 69 | @Override 70 | public String toString() { 71 | StringBuilder sb = new StringBuilder(); 72 | sb.append(getClass().getSimpleName()); 73 | sb.append(" ["); 74 | sb.append("Hash = ").append(hashCode()); 75 | sb.append(", id=").append(id); 76 | sb.append(", userId=").append(userId); 77 | sb.append(", name=").append(name); 78 | sb.append(", url=").append(url); 79 | sb.append(", createTime=").append(createTime); 80 | sb.append(", description=").append(description); 81 | sb.append(", serialVersionUID=").append(serialVersionUID); 82 | sb.append("]"); 83 | return sb.toString(); 84 | } 85 | } -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/UmsGalleryExample.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | public class UmsGalleryExample { 8 | protected String orderByClause; 9 | 10 | protected boolean distinct; 11 | 12 | protected List oredCriteria; 13 | 14 | public UmsGalleryExample() { 15 | oredCriteria = new ArrayList(); 16 | } 17 | 18 | public void setOrderByClause(String orderByClause) { 19 | this.orderByClause = orderByClause; 20 | } 21 | 22 | public String getOrderByClause() { 23 | return orderByClause; 24 | } 25 | 26 | public void setDistinct(boolean distinct) { 27 | this.distinct = distinct; 28 | } 29 | 30 | public boolean isDistinct() { 31 | return distinct; 32 | } 33 | 34 | public List getOredCriteria() { 35 | return oredCriteria; 36 | } 37 | 38 | public void or(Criteria criteria) { 39 | oredCriteria.add(criteria); 40 | } 41 | 42 | public Criteria or() { 43 | Criteria criteria = createCriteriaInternal(); 44 | oredCriteria.add(criteria); 45 | return criteria; 46 | } 47 | 48 | public Criteria createCriteria() { 49 | Criteria criteria = createCriteriaInternal(); 50 | if (oredCriteria.size() == 0) { 51 | oredCriteria.add(criteria); 52 | } 53 | return criteria; 54 | } 55 | 56 | protected Criteria createCriteriaInternal() { 57 | Criteria criteria = new Criteria(); 58 | return criteria; 59 | } 60 | 61 | public void clear() { 62 | oredCriteria.clear(); 63 | orderByClause = null; 64 | distinct = false; 65 | } 66 | 67 | protected abstract static class GeneratedCriteria { 68 | protected List criteria; 69 | 70 | protected GeneratedCriteria() { 71 | super(); 72 | criteria = new ArrayList(); 73 | } 74 | 75 | public boolean isValid() { 76 | return criteria.size() > 0; 77 | } 78 | 79 | public List getAllCriteria() { 80 | return criteria; 81 | } 82 | 83 | public List getCriteria() { 84 | return criteria; 85 | } 86 | 87 | protected void addCriterion(String condition) { 88 | if (condition == null) { 89 | throw new RuntimeException("Value for condition cannot be null"); 90 | } 91 | criteria.add(new Criterion(condition)); 92 | } 93 | 94 | protected void addCriterion(String condition, Object value, String property) { 95 | if (value == null) { 96 | throw new RuntimeException("Value for " + property + " cannot be null"); 97 | } 98 | criteria.add(new Criterion(condition, value)); 99 | } 100 | 101 | protected void addCriterion(String condition, Object value1, Object value2, String property) { 102 | if (value1 == null || value2 == null) { 103 | throw new RuntimeException("Between values for " + property + " cannot be null"); 104 | } 105 | criteria.add(new Criterion(condition, value1, value2)); 106 | } 107 | 108 | public Criteria andIdIsNull() { 109 | addCriterion("id is null"); 110 | return (Criteria) this; 111 | } 112 | 113 | public Criteria andIdIsNotNull() { 114 | addCriterion("id is not null"); 115 | return (Criteria) this; 116 | } 117 | 118 | public Criteria andIdEqualTo(Integer value) { 119 | addCriterion("id =", value, "id"); 120 | return (Criteria) this; 121 | } 122 | 123 | public Criteria andIdNotEqualTo(Integer value) { 124 | addCriterion("id <>", value, "id"); 125 | return (Criteria) this; 126 | } 127 | 128 | public Criteria andIdGreaterThan(Integer value) { 129 | addCriterion("id >", value, "id"); 130 | return (Criteria) this; 131 | } 132 | 133 | public Criteria andIdGreaterThanOrEqualTo(Integer value) { 134 | addCriterion("id >=", value, "id"); 135 | return (Criteria) this; 136 | } 137 | 138 | public Criteria andIdLessThan(Integer value) { 139 | addCriterion("id <", value, "id"); 140 | return (Criteria) this; 141 | } 142 | 143 | public Criteria andIdLessThanOrEqualTo(Integer value) { 144 | addCriterion("id <=", value, "id"); 145 | return (Criteria) this; 146 | } 147 | 148 | public Criteria andIdIn(List values) { 149 | addCriterion("id in", values, "id"); 150 | return (Criteria) this; 151 | } 152 | 153 | public Criteria andIdNotIn(List values) { 154 | addCriterion("id not in", values, "id"); 155 | return (Criteria) this; 156 | } 157 | 158 | public Criteria andIdBetween(Integer value1, Integer value2) { 159 | addCriterion("id between", value1, value2, "id"); 160 | return (Criteria) this; 161 | } 162 | 163 | public Criteria andIdNotBetween(Integer value1, Integer value2) { 164 | addCriterion("id not between", value1, value2, "id"); 165 | return (Criteria) this; 166 | } 167 | 168 | public Criteria andUserIdIsNull() { 169 | addCriterion("user_id is null"); 170 | return (Criteria) this; 171 | } 172 | 173 | public Criteria andUserIdIsNotNull() { 174 | addCriterion("user_id is not null"); 175 | return (Criteria) this; 176 | } 177 | 178 | public Criteria andUserIdEqualTo(Integer value) { 179 | addCriterion("user_id =", value, "userId"); 180 | return (Criteria) this; 181 | } 182 | 183 | public Criteria andUserIdNotEqualTo(Integer value) { 184 | addCriterion("user_id <>", value, "userId"); 185 | return (Criteria) this; 186 | } 187 | 188 | public Criteria andUserIdGreaterThan(Integer value) { 189 | addCriterion("user_id >", value, "userId"); 190 | return (Criteria) this; 191 | } 192 | 193 | public Criteria andUserIdGreaterThanOrEqualTo(Integer value) { 194 | addCriterion("user_id >=", value, "userId"); 195 | return (Criteria) this; 196 | } 197 | 198 | public Criteria andUserIdLessThan(Integer value) { 199 | addCriterion("user_id <", value, "userId"); 200 | return (Criteria) this; 201 | } 202 | 203 | public Criteria andUserIdLessThanOrEqualTo(Integer value) { 204 | addCriterion("user_id <=", value, "userId"); 205 | return (Criteria) this; 206 | } 207 | 208 | public Criteria andUserIdIn(List values) { 209 | addCriterion("user_id in", values, "userId"); 210 | return (Criteria) this; 211 | } 212 | 213 | public Criteria andUserIdNotIn(List values) { 214 | addCriterion("user_id not in", values, "userId"); 215 | return (Criteria) this; 216 | } 217 | 218 | public Criteria andUserIdBetween(Integer value1, Integer value2) { 219 | addCriterion("user_id between", value1, value2, "userId"); 220 | return (Criteria) this; 221 | } 222 | 223 | public Criteria andUserIdNotBetween(Integer value1, Integer value2) { 224 | addCriterion("user_id not between", value1, value2, "userId"); 225 | return (Criteria) this; 226 | } 227 | 228 | public Criteria andNameIsNull() { 229 | addCriterion("name is null"); 230 | return (Criteria) this; 231 | } 232 | 233 | public Criteria andNameIsNotNull() { 234 | addCriterion("name is not null"); 235 | return (Criteria) this; 236 | } 237 | 238 | public Criteria andNameEqualTo(String value) { 239 | addCriterion("name =", value, "name"); 240 | return (Criteria) this; 241 | } 242 | 243 | public Criteria andNameNotEqualTo(String value) { 244 | addCriterion("name <>", value, "name"); 245 | return (Criteria) this; 246 | } 247 | 248 | public Criteria andNameGreaterThan(String value) { 249 | addCriterion("name >", value, "name"); 250 | return (Criteria) this; 251 | } 252 | 253 | public Criteria andNameGreaterThanOrEqualTo(String value) { 254 | addCriterion("name >=", value, "name"); 255 | return (Criteria) this; 256 | } 257 | 258 | public Criteria andNameLessThan(String value) { 259 | addCriterion("name <", value, "name"); 260 | return (Criteria) this; 261 | } 262 | 263 | public Criteria andNameLessThanOrEqualTo(String value) { 264 | addCriterion("name <=", value, "name"); 265 | return (Criteria) this; 266 | } 267 | 268 | public Criteria andNameLike(String value) { 269 | addCriterion("name like", value, "name"); 270 | return (Criteria) this; 271 | } 272 | 273 | public Criteria andNameNotLike(String value) { 274 | addCriterion("name not like", value, "name"); 275 | return (Criteria) this; 276 | } 277 | 278 | public Criteria andNameIn(List values) { 279 | addCriterion("name in", values, "name"); 280 | return (Criteria) this; 281 | } 282 | 283 | public Criteria andNameNotIn(List values) { 284 | addCriterion("name not in", values, "name"); 285 | return (Criteria) this; 286 | } 287 | 288 | public Criteria andNameBetween(String value1, String value2) { 289 | addCriterion("name between", value1, value2, "name"); 290 | return (Criteria) this; 291 | } 292 | 293 | public Criteria andNameNotBetween(String value1, String value2) { 294 | addCriterion("name not between", value1, value2, "name"); 295 | return (Criteria) this; 296 | } 297 | 298 | public Criteria andUrlIsNull() { 299 | addCriterion("url is null"); 300 | return (Criteria) this; 301 | } 302 | 303 | public Criteria andUrlIsNotNull() { 304 | addCriterion("url is not null"); 305 | return (Criteria) this; 306 | } 307 | 308 | public Criteria andUrlEqualTo(String value) { 309 | addCriterion("url =", value, "url"); 310 | return (Criteria) this; 311 | } 312 | 313 | public Criteria andUrlNotEqualTo(String value) { 314 | addCriterion("url <>", value, "url"); 315 | return (Criteria) this; 316 | } 317 | 318 | public Criteria andUrlGreaterThan(String value) { 319 | addCriterion("url >", value, "url"); 320 | return (Criteria) this; 321 | } 322 | 323 | public Criteria andUrlGreaterThanOrEqualTo(String value) { 324 | addCriterion("url >=", value, "url"); 325 | return (Criteria) this; 326 | } 327 | 328 | public Criteria andUrlLessThan(String value) { 329 | addCriterion("url <", value, "url"); 330 | return (Criteria) this; 331 | } 332 | 333 | public Criteria andUrlLessThanOrEqualTo(String value) { 334 | addCriterion("url <=", value, "url"); 335 | return (Criteria) this; 336 | } 337 | 338 | public Criteria andUrlLike(String value) { 339 | addCriterion("url like", value, "url"); 340 | return (Criteria) this; 341 | } 342 | 343 | public Criteria andUrlNotLike(String value) { 344 | addCriterion("url not like", value, "url"); 345 | return (Criteria) this; 346 | } 347 | 348 | public Criteria andUrlIn(List values) { 349 | addCriterion("url in", values, "url"); 350 | return (Criteria) this; 351 | } 352 | 353 | public Criteria andUrlNotIn(List values) { 354 | addCriterion("url not in", values, "url"); 355 | return (Criteria) this; 356 | } 357 | 358 | public Criteria andUrlBetween(String value1, String value2) { 359 | addCriterion("url between", value1, value2, "url"); 360 | return (Criteria) this; 361 | } 362 | 363 | public Criteria andUrlNotBetween(String value1, String value2) { 364 | addCriterion("url not between", value1, value2, "url"); 365 | return (Criteria) this; 366 | } 367 | 368 | public Criteria andCreateTimeIsNull() { 369 | addCriterion("create_time is null"); 370 | return (Criteria) this; 371 | } 372 | 373 | public Criteria andCreateTimeIsNotNull() { 374 | addCriterion("create_time is not null"); 375 | return (Criteria) this; 376 | } 377 | 378 | public Criteria andCreateTimeEqualTo(Date value) { 379 | addCriterion("create_time =", value, "createTime"); 380 | return (Criteria) this; 381 | } 382 | 383 | public Criteria andCreateTimeNotEqualTo(Date value) { 384 | addCriterion("create_time <>", value, "createTime"); 385 | return (Criteria) this; 386 | } 387 | 388 | public Criteria andCreateTimeGreaterThan(Date value) { 389 | addCriterion("create_time >", value, "createTime"); 390 | return (Criteria) this; 391 | } 392 | 393 | public Criteria andCreateTimeGreaterThanOrEqualTo(Date value) { 394 | addCriterion("create_time >=", value, "createTime"); 395 | return (Criteria) this; 396 | } 397 | 398 | public Criteria andCreateTimeLessThan(Date value) { 399 | addCriterion("create_time <", value, "createTime"); 400 | return (Criteria) this; 401 | } 402 | 403 | public Criteria andCreateTimeLessThanOrEqualTo(Date value) { 404 | addCriterion("create_time <=", value, "createTime"); 405 | return (Criteria) this; 406 | } 407 | 408 | public Criteria andCreateTimeIn(List values) { 409 | addCriterion("create_time in", values, "createTime"); 410 | return (Criteria) this; 411 | } 412 | 413 | public Criteria andCreateTimeNotIn(List values) { 414 | addCriterion("create_time not in", values, "createTime"); 415 | return (Criteria) this; 416 | } 417 | 418 | public Criteria andCreateTimeBetween(Date value1, Date value2) { 419 | addCriterion("create_time between", value1, value2, "createTime"); 420 | return (Criteria) this; 421 | } 422 | 423 | public Criteria andCreateTimeNotBetween(Date value1, Date value2) { 424 | addCriterion("create_time not between", value1, value2, "createTime"); 425 | return (Criteria) this; 426 | } 427 | } 428 | 429 | public static class Criteria extends GeneratedCriteria { 430 | 431 | protected Criteria() { 432 | super(); 433 | } 434 | } 435 | 436 | public static class Criterion { 437 | private String condition; 438 | 439 | private Object value; 440 | 441 | private Object secondValue; 442 | 443 | private boolean noValue; 444 | 445 | private boolean singleValue; 446 | 447 | private boolean betweenValue; 448 | 449 | private boolean listValue; 450 | 451 | private String typeHandler; 452 | 453 | public String getCondition() { 454 | return condition; 455 | } 456 | 457 | public Object getValue() { 458 | return value; 459 | } 460 | 461 | public Object getSecondValue() { 462 | return secondValue; 463 | } 464 | 465 | public boolean isNoValue() { 466 | return noValue; 467 | } 468 | 469 | public boolean isSingleValue() { 470 | return singleValue; 471 | } 472 | 473 | public boolean isBetweenValue() { 474 | return betweenValue; 475 | } 476 | 477 | public boolean isListValue() { 478 | return listValue; 479 | } 480 | 481 | public String getTypeHandler() { 482 | return typeHandler; 483 | } 484 | 485 | protected Criterion(String condition) { 486 | super(); 487 | this.condition = condition; 488 | this.typeHandler = null; 489 | this.noValue = true; 490 | } 491 | 492 | protected Criterion(String condition, Object value, String typeHandler) { 493 | super(); 494 | this.condition = condition; 495 | this.value = value; 496 | this.typeHandler = typeHandler; 497 | if (value instanceof List) { 498 | this.listValue = true; 499 | } else { 500 | this.singleValue = true; 501 | } 502 | } 503 | 504 | protected Criterion(String condition, Object value) { 505 | this(condition, value, null); 506 | } 507 | 508 | protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { 509 | super(); 510 | this.condition = condition; 511 | this.value = value; 512 | this.secondValue = secondValue; 513 | this.typeHandler = typeHandler; 514 | this.betweenValue = true; 515 | } 516 | 517 | protected Criterion(String condition, Object value, Object secondValue) { 518 | this(condition, value, secondValue, null); 519 | } 520 | } 521 | } -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/User.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | public class User implements Serializable { 7 | private Integer id; 8 | 9 | private String loginname; 10 | 11 | private String nickname; 12 | 13 | private String password; 14 | 15 | private String mobilephone; 16 | 17 | private String headerurl; 18 | 19 | private Date logintime; 20 | 21 | private Date createtime; 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | public Integer getId() { 26 | return id; 27 | } 28 | 29 | public void setId(Integer id) { 30 | this.id = id; 31 | } 32 | 33 | public String getLoginname() { 34 | return loginname; 35 | } 36 | 37 | public void setLoginname(String loginname) { 38 | this.loginname = loginname; 39 | } 40 | 41 | public String getNickname() { 42 | return nickname; 43 | } 44 | 45 | public void setNickname(String nickname) { 46 | this.nickname = nickname; 47 | } 48 | 49 | public String getPassword() { 50 | return password; 51 | } 52 | 53 | public void setPassword(String password) { 54 | this.password = password; 55 | } 56 | 57 | public String getMobilephone() { 58 | return mobilephone; 59 | } 60 | 61 | public void setMobilephone(String mobilephone) { 62 | this.mobilephone = mobilephone; 63 | } 64 | 65 | public String getHeaderurl() { 66 | return headerurl; 67 | } 68 | 69 | public void setHeaderurl(String headerurl) { 70 | this.headerurl = headerurl; 71 | } 72 | 73 | public Date getLogintime() { 74 | return logintime; 75 | } 76 | 77 | public void setLogintime(Date logintime) { 78 | this.logintime = logintime; 79 | } 80 | 81 | public Date getCreatetime() { 82 | return createtime; 83 | } 84 | 85 | public void setCreatetime(Date createtime) { 86 | this.createtime = createtime; 87 | } 88 | 89 | @Override 90 | public String toString() { 91 | StringBuilder sb = new StringBuilder(); 92 | sb.append(getClass().getSimpleName()); 93 | sb.append(" ["); 94 | sb.append("Hash = ").append(hashCode()); 95 | sb.append(", id=").append(id); 96 | sb.append(", loginname=").append(loginname); 97 | sb.append(", nickname=").append(nickname); 98 | sb.append(", password=").append(password); 99 | sb.append(", mobilephone=").append(mobilephone); 100 | sb.append(", headerurl=").append(headerurl); 101 | sb.append(", logintime=").append(logintime); 102 | sb.append(", createtime=").append(createtime); 103 | sb.append(", serialVersionUID=").append(serialVersionUID); 104 | sb.append("]"); 105 | return sb.toString(); 106 | } 107 | } -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/UserExample.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | 7 | public class UserExample { 8 | protected String orderByClause; 9 | 10 | protected boolean distinct; 11 | 12 | protected List oredCriteria; 13 | 14 | public UserExample() { 15 | oredCriteria = new ArrayList(); 16 | } 17 | 18 | public void setOrderByClause(String orderByClause) { 19 | this.orderByClause = orderByClause; 20 | } 21 | 22 | public String getOrderByClause() { 23 | return orderByClause; 24 | } 25 | 26 | public void setDistinct(boolean distinct) { 27 | this.distinct = distinct; 28 | } 29 | 30 | public boolean isDistinct() { 31 | return distinct; 32 | } 33 | 34 | public List getOredCriteria() { 35 | return oredCriteria; 36 | } 37 | 38 | public void or(Criteria criteria) { 39 | oredCriteria.add(criteria); 40 | } 41 | 42 | public Criteria or() { 43 | Criteria criteria = createCriteriaInternal(); 44 | oredCriteria.add(criteria); 45 | return criteria; 46 | } 47 | 48 | public Criteria createCriteria() { 49 | Criteria criteria = createCriteriaInternal(); 50 | if (oredCriteria.size() == 0) { 51 | oredCriteria.add(criteria); 52 | } 53 | return criteria; 54 | } 55 | 56 | protected Criteria createCriteriaInternal() { 57 | Criteria criteria = new Criteria(); 58 | return criteria; 59 | } 60 | 61 | public void clear() { 62 | oredCriteria.clear(); 63 | orderByClause = null; 64 | distinct = false; 65 | } 66 | 67 | protected abstract static class GeneratedCriteria { 68 | protected List criteria; 69 | 70 | protected GeneratedCriteria() { 71 | super(); 72 | criteria = new ArrayList(); 73 | } 74 | 75 | public boolean isValid() { 76 | return criteria.size() > 0; 77 | } 78 | 79 | public List getAllCriteria() { 80 | return criteria; 81 | } 82 | 83 | public List getCriteria() { 84 | return criteria; 85 | } 86 | 87 | protected void addCriterion(String condition) { 88 | if (condition == null) { 89 | throw new RuntimeException("Value for condition cannot be null"); 90 | } 91 | criteria.add(new Criterion(condition)); 92 | } 93 | 94 | protected void addCriterion(String condition, Object value, String property) { 95 | if (value == null) { 96 | throw new RuntimeException("Value for " + property + " cannot be null"); 97 | } 98 | criteria.add(new Criterion(condition, value)); 99 | } 100 | 101 | protected void addCriterion(String condition, Object value1, Object value2, String property) { 102 | if (value1 == null || value2 == null) { 103 | throw new RuntimeException("Between values for " + property + " cannot be null"); 104 | } 105 | criteria.add(new Criterion(condition, value1, value2)); 106 | } 107 | 108 | public Criteria andIdIsNull() { 109 | addCriterion("id is null"); 110 | return (Criteria) this; 111 | } 112 | 113 | public Criteria andIdIsNotNull() { 114 | addCriterion("id is not null"); 115 | return (Criteria) this; 116 | } 117 | 118 | public Criteria andIdEqualTo(Integer value) { 119 | addCriterion("id =", value, "id"); 120 | return (Criteria) this; 121 | } 122 | 123 | public Criteria andIdNotEqualTo(Integer value) { 124 | addCriterion("id <>", value, "id"); 125 | return (Criteria) this; 126 | } 127 | 128 | public Criteria andIdGreaterThan(Integer value) { 129 | addCriterion("id >", value, "id"); 130 | return (Criteria) this; 131 | } 132 | 133 | public Criteria andIdGreaterThanOrEqualTo(Integer value) { 134 | addCriterion("id >=", value, "id"); 135 | return (Criteria) this; 136 | } 137 | 138 | public Criteria andIdLessThan(Integer value) { 139 | addCriterion("id <", value, "id"); 140 | return (Criteria) this; 141 | } 142 | 143 | public Criteria andIdLessThanOrEqualTo(Integer value) { 144 | addCriterion("id <=", value, "id"); 145 | return (Criteria) this; 146 | } 147 | 148 | public Criteria andIdIn(List values) { 149 | addCriterion("id in", values, "id"); 150 | return (Criteria) this; 151 | } 152 | 153 | public Criteria andIdNotIn(List values) { 154 | addCriterion("id not in", values, "id"); 155 | return (Criteria) this; 156 | } 157 | 158 | public Criteria andIdBetween(Integer value1, Integer value2) { 159 | addCriterion("id between", value1, value2, "id"); 160 | return (Criteria) this; 161 | } 162 | 163 | public Criteria andIdNotBetween(Integer value1, Integer value2) { 164 | addCriterion("id not between", value1, value2, "id"); 165 | return (Criteria) this; 166 | } 167 | 168 | public Criteria andLoginnameIsNull() { 169 | addCriterion("loginName is null"); 170 | return (Criteria) this; 171 | } 172 | 173 | public Criteria andLoginnameIsNotNull() { 174 | addCriterion("loginName is not null"); 175 | return (Criteria) this; 176 | } 177 | 178 | public Criteria andLoginnameEqualTo(String value) { 179 | addCriterion("loginName =", value, "loginname"); 180 | return (Criteria) this; 181 | } 182 | 183 | public Criteria andLoginnameNotEqualTo(String value) { 184 | addCriterion("loginName <>", value, "loginname"); 185 | return (Criteria) this; 186 | } 187 | 188 | public Criteria andLoginnameGreaterThan(String value) { 189 | addCriterion("loginName >", value, "loginname"); 190 | return (Criteria) this; 191 | } 192 | 193 | public Criteria andLoginnameGreaterThanOrEqualTo(String value) { 194 | addCriterion("loginName >=", value, "loginname"); 195 | return (Criteria) this; 196 | } 197 | 198 | public Criteria andLoginnameLessThan(String value) { 199 | addCriterion("loginName <", value, "loginname"); 200 | return (Criteria) this; 201 | } 202 | 203 | public Criteria andLoginnameLessThanOrEqualTo(String value) { 204 | addCriterion("loginName <=", value, "loginname"); 205 | return (Criteria) this; 206 | } 207 | 208 | public Criteria andLoginnameLike(String value) { 209 | addCriterion("loginName like", value, "loginname"); 210 | return (Criteria) this; 211 | } 212 | 213 | public Criteria andLoginnameNotLike(String value) { 214 | addCriterion("loginName not like", value, "loginname"); 215 | return (Criteria) this; 216 | } 217 | 218 | public Criteria andLoginnameIn(List values) { 219 | addCriterion("loginName in", values, "loginname"); 220 | return (Criteria) this; 221 | } 222 | 223 | public Criteria andLoginnameNotIn(List values) { 224 | addCriterion("loginName not in", values, "loginname"); 225 | return (Criteria) this; 226 | } 227 | 228 | public Criteria andLoginnameBetween(String value1, String value2) { 229 | addCriterion("loginName between", value1, value2, "loginname"); 230 | return (Criteria) this; 231 | } 232 | 233 | public Criteria andLoginnameNotBetween(String value1, String value2) { 234 | addCriterion("loginName not between", value1, value2, "loginname"); 235 | return (Criteria) this; 236 | } 237 | 238 | public Criteria andNicknameIsNull() { 239 | addCriterion("nickName is null"); 240 | return (Criteria) this; 241 | } 242 | 243 | public Criteria andNicknameIsNotNull() { 244 | addCriterion("nickName is not null"); 245 | return (Criteria) this; 246 | } 247 | 248 | public Criteria andNicknameEqualTo(String value) { 249 | addCriterion("nickName =", value, "nickname"); 250 | return (Criteria) this; 251 | } 252 | 253 | public Criteria andNicknameNotEqualTo(String value) { 254 | addCriterion("nickName <>", value, "nickname"); 255 | return (Criteria) this; 256 | } 257 | 258 | public Criteria andNicknameGreaterThan(String value) { 259 | addCriterion("nickName >", value, "nickname"); 260 | return (Criteria) this; 261 | } 262 | 263 | public Criteria andNicknameGreaterThanOrEqualTo(String value) { 264 | addCriterion("nickName >=", value, "nickname"); 265 | return (Criteria) this; 266 | } 267 | 268 | public Criteria andNicknameLessThan(String value) { 269 | addCriterion("nickName <", value, "nickname"); 270 | return (Criteria) this; 271 | } 272 | 273 | public Criteria andNicknameLessThanOrEqualTo(String value) { 274 | addCriterion("nickName <=", value, "nickname"); 275 | return (Criteria) this; 276 | } 277 | 278 | public Criteria andNicknameLike(String value) { 279 | addCriterion("nickName like", value, "nickname"); 280 | return (Criteria) this; 281 | } 282 | 283 | public Criteria andNicknameNotLike(String value) { 284 | addCriterion("nickName not like", value, "nickname"); 285 | return (Criteria) this; 286 | } 287 | 288 | public Criteria andNicknameIn(List values) { 289 | addCriterion("nickName in", values, "nickname"); 290 | return (Criteria) this; 291 | } 292 | 293 | public Criteria andNicknameNotIn(List values) { 294 | addCriterion("nickName not in", values, "nickname"); 295 | return (Criteria) this; 296 | } 297 | 298 | public Criteria andNicknameBetween(String value1, String value2) { 299 | addCriterion("nickName between", value1, value2, "nickname"); 300 | return (Criteria) this; 301 | } 302 | 303 | public Criteria andNicknameNotBetween(String value1, String value2) { 304 | addCriterion("nickName not between", value1, value2, "nickname"); 305 | return (Criteria) this; 306 | } 307 | 308 | public Criteria andPasswordIsNull() { 309 | addCriterion("password is null"); 310 | return (Criteria) this; 311 | } 312 | 313 | public Criteria andPasswordIsNotNull() { 314 | addCriterion("password is not null"); 315 | return (Criteria) this; 316 | } 317 | 318 | public Criteria andPasswordEqualTo(String value) { 319 | addCriterion("password =", value, "password"); 320 | return (Criteria) this; 321 | } 322 | 323 | public Criteria andPasswordNotEqualTo(String value) { 324 | addCriterion("password <>", value, "password"); 325 | return (Criteria) this; 326 | } 327 | 328 | public Criteria andPasswordGreaterThan(String value) { 329 | addCriterion("password >", value, "password"); 330 | return (Criteria) this; 331 | } 332 | 333 | public Criteria andPasswordGreaterThanOrEqualTo(String value) { 334 | addCriterion("password >=", value, "password"); 335 | return (Criteria) this; 336 | } 337 | 338 | public Criteria andPasswordLessThan(String value) { 339 | addCriterion("password <", value, "password"); 340 | return (Criteria) this; 341 | } 342 | 343 | public Criteria andPasswordLessThanOrEqualTo(String value) { 344 | addCriterion("password <=", value, "password"); 345 | return (Criteria) this; 346 | } 347 | 348 | public Criteria andPasswordLike(String value) { 349 | addCriterion("password like", value, "password"); 350 | return (Criteria) this; 351 | } 352 | 353 | public Criteria andPasswordNotLike(String value) { 354 | addCriterion("password not like", value, "password"); 355 | return (Criteria) this; 356 | } 357 | 358 | public Criteria andPasswordIn(List values) { 359 | addCriterion("password in", values, "password"); 360 | return (Criteria) this; 361 | } 362 | 363 | public Criteria andPasswordNotIn(List values) { 364 | addCriterion("password not in", values, "password"); 365 | return (Criteria) this; 366 | } 367 | 368 | public Criteria andPasswordBetween(String value1, String value2) { 369 | addCriterion("password between", value1, value2, "password"); 370 | return (Criteria) this; 371 | } 372 | 373 | public Criteria andPasswordNotBetween(String value1, String value2) { 374 | addCriterion("password not between", value1, value2, "password"); 375 | return (Criteria) this; 376 | } 377 | 378 | public Criteria andMobilephoneIsNull() { 379 | addCriterion("mobilePhone is null"); 380 | return (Criteria) this; 381 | } 382 | 383 | public Criteria andMobilephoneIsNotNull() { 384 | addCriterion("mobilePhone is not null"); 385 | return (Criteria) this; 386 | } 387 | 388 | public Criteria andMobilephoneEqualTo(String value) { 389 | addCriterion("mobilePhone =", value, "mobilephone"); 390 | return (Criteria) this; 391 | } 392 | 393 | public Criteria andMobilephoneNotEqualTo(String value) { 394 | addCriterion("mobilePhone <>", value, "mobilephone"); 395 | return (Criteria) this; 396 | } 397 | 398 | public Criteria andMobilephoneGreaterThan(String value) { 399 | addCriterion("mobilePhone >", value, "mobilephone"); 400 | return (Criteria) this; 401 | } 402 | 403 | public Criteria andMobilephoneGreaterThanOrEqualTo(String value) { 404 | addCriterion("mobilePhone >=", value, "mobilephone"); 405 | return (Criteria) this; 406 | } 407 | 408 | public Criteria andMobilephoneLessThan(String value) { 409 | addCriterion("mobilePhone <", value, "mobilephone"); 410 | return (Criteria) this; 411 | } 412 | 413 | public Criteria andMobilephoneLessThanOrEqualTo(String value) { 414 | addCriterion("mobilePhone <=", value, "mobilephone"); 415 | return (Criteria) this; 416 | } 417 | 418 | public Criteria andMobilephoneLike(String value) { 419 | addCriterion("mobilePhone like", value, "mobilephone"); 420 | return (Criteria) this; 421 | } 422 | 423 | public Criteria andMobilephoneNotLike(String value) { 424 | addCriterion("mobilePhone not like", value, "mobilephone"); 425 | return (Criteria) this; 426 | } 427 | 428 | public Criteria andMobilephoneIn(List values) { 429 | addCriterion("mobilePhone in", values, "mobilephone"); 430 | return (Criteria) this; 431 | } 432 | 433 | public Criteria andMobilephoneNotIn(List values) { 434 | addCriterion("mobilePhone not in", values, "mobilephone"); 435 | return (Criteria) this; 436 | } 437 | 438 | public Criteria andMobilephoneBetween(String value1, String value2) { 439 | addCriterion("mobilePhone between", value1, value2, "mobilephone"); 440 | return (Criteria) this; 441 | } 442 | 443 | public Criteria andMobilephoneNotBetween(String value1, String value2) { 444 | addCriterion("mobilePhone not between", value1, value2, "mobilephone"); 445 | return (Criteria) this; 446 | } 447 | 448 | public Criteria andHeaderurlIsNull() { 449 | addCriterion("headerUrl is null"); 450 | return (Criteria) this; 451 | } 452 | 453 | public Criteria andHeaderurlIsNotNull() { 454 | addCriterion("headerUrl is not null"); 455 | return (Criteria) this; 456 | } 457 | 458 | public Criteria andHeaderurlEqualTo(String value) { 459 | addCriterion("headerUrl =", value, "headerurl"); 460 | return (Criteria) this; 461 | } 462 | 463 | public Criteria andHeaderurlNotEqualTo(String value) { 464 | addCriterion("headerUrl <>", value, "headerurl"); 465 | return (Criteria) this; 466 | } 467 | 468 | public Criteria andHeaderurlGreaterThan(String value) { 469 | addCriterion("headerUrl >", value, "headerurl"); 470 | return (Criteria) this; 471 | } 472 | 473 | public Criteria andHeaderurlGreaterThanOrEqualTo(String value) { 474 | addCriterion("headerUrl >=", value, "headerurl"); 475 | return (Criteria) this; 476 | } 477 | 478 | public Criteria andHeaderurlLessThan(String value) { 479 | addCriterion("headerUrl <", value, "headerurl"); 480 | return (Criteria) this; 481 | } 482 | 483 | public Criteria andHeaderurlLessThanOrEqualTo(String value) { 484 | addCriterion("headerUrl <=", value, "headerurl"); 485 | return (Criteria) this; 486 | } 487 | 488 | public Criteria andHeaderurlLike(String value) { 489 | addCriterion("headerUrl like", value, "headerurl"); 490 | return (Criteria) this; 491 | } 492 | 493 | public Criteria andHeaderurlNotLike(String value) { 494 | addCriterion("headerUrl not like", value, "headerurl"); 495 | return (Criteria) this; 496 | } 497 | 498 | public Criteria andHeaderurlIn(List values) { 499 | addCriterion("headerUrl in", values, "headerurl"); 500 | return (Criteria) this; 501 | } 502 | 503 | public Criteria andHeaderurlNotIn(List values) { 504 | addCriterion("headerUrl not in", values, "headerurl"); 505 | return (Criteria) this; 506 | } 507 | 508 | public Criteria andHeaderurlBetween(String value1, String value2) { 509 | addCriterion("headerUrl between", value1, value2, "headerurl"); 510 | return (Criteria) this; 511 | } 512 | 513 | public Criteria andHeaderurlNotBetween(String value1, String value2) { 514 | addCriterion("headerUrl not between", value1, value2, "headerurl"); 515 | return (Criteria) this; 516 | } 517 | 518 | public Criteria andLogintimeIsNull() { 519 | addCriterion("loginTime is null"); 520 | return (Criteria) this; 521 | } 522 | 523 | public Criteria andLogintimeIsNotNull() { 524 | addCriterion("loginTime is not null"); 525 | return (Criteria) this; 526 | } 527 | 528 | public Criteria andLogintimeEqualTo(Date value) { 529 | addCriterion("loginTime =", value, "logintime"); 530 | return (Criteria) this; 531 | } 532 | 533 | public Criteria andLogintimeNotEqualTo(Date value) { 534 | addCriterion("loginTime <>", value, "logintime"); 535 | return (Criteria) this; 536 | } 537 | 538 | public Criteria andLogintimeGreaterThan(Date value) { 539 | addCriterion("loginTime >", value, "logintime"); 540 | return (Criteria) this; 541 | } 542 | 543 | public Criteria andLogintimeGreaterThanOrEqualTo(Date value) { 544 | addCriterion("loginTime >=", value, "logintime"); 545 | return (Criteria) this; 546 | } 547 | 548 | public Criteria andLogintimeLessThan(Date value) { 549 | addCriterion("loginTime <", value, "logintime"); 550 | return (Criteria) this; 551 | } 552 | 553 | public Criteria andLogintimeLessThanOrEqualTo(Date value) { 554 | addCriterion("loginTime <=", value, "logintime"); 555 | return (Criteria) this; 556 | } 557 | 558 | public Criteria andLogintimeIn(List values) { 559 | addCriterion("loginTime in", values, "logintime"); 560 | return (Criteria) this; 561 | } 562 | 563 | public Criteria andLogintimeNotIn(List values) { 564 | addCriterion("loginTime not in", values, "logintime"); 565 | return (Criteria) this; 566 | } 567 | 568 | public Criteria andLogintimeBetween(Date value1, Date value2) { 569 | addCriterion("loginTime between", value1, value2, "logintime"); 570 | return (Criteria) this; 571 | } 572 | 573 | public Criteria andLogintimeNotBetween(Date value1, Date value2) { 574 | addCriterion("loginTime not between", value1, value2, "logintime"); 575 | return (Criteria) this; 576 | } 577 | 578 | public Criteria andCreatetimeIsNull() { 579 | addCriterion("createTime is null"); 580 | return (Criteria) this; 581 | } 582 | 583 | public Criteria andCreatetimeIsNotNull() { 584 | addCriterion("createTime is not null"); 585 | return (Criteria) this; 586 | } 587 | 588 | public Criteria andCreatetimeEqualTo(Date value) { 589 | addCriterion("createTime =", value, "createtime"); 590 | return (Criteria) this; 591 | } 592 | 593 | public Criteria andCreatetimeNotEqualTo(Date value) { 594 | addCriterion("createTime <>", value, "createtime"); 595 | return (Criteria) this; 596 | } 597 | 598 | public Criteria andCreatetimeGreaterThan(Date value) { 599 | addCriterion("createTime >", value, "createtime"); 600 | return (Criteria) this; 601 | } 602 | 603 | public Criteria andCreatetimeGreaterThanOrEqualTo(Date value) { 604 | addCriterion("createTime >=", value, "createtime"); 605 | return (Criteria) this; 606 | } 607 | 608 | public Criteria andCreatetimeLessThan(Date value) { 609 | addCriterion("createTime <", value, "createtime"); 610 | return (Criteria) this; 611 | } 612 | 613 | public Criteria andCreatetimeLessThanOrEqualTo(Date value) { 614 | addCriterion("createTime <=", value, "createtime"); 615 | return (Criteria) this; 616 | } 617 | 618 | public Criteria andCreatetimeIn(List values) { 619 | addCriterion("createTime in", values, "createtime"); 620 | return (Criteria) this; 621 | } 622 | 623 | public Criteria andCreatetimeNotIn(List values) { 624 | addCriterion("createTime not in", values, "createtime"); 625 | return (Criteria) this; 626 | } 627 | 628 | public Criteria andCreatetimeBetween(Date value1, Date value2) { 629 | addCriterion("createTime between", value1, value2, "createtime"); 630 | return (Criteria) this; 631 | } 632 | 633 | public Criteria andCreatetimeNotBetween(Date value1, Date value2) { 634 | addCriterion("createTime not between", value1, value2, "createtime"); 635 | return (Criteria) this; 636 | } 637 | } 638 | 639 | public static class Criteria extends GeneratedCriteria { 640 | 641 | protected Criteria() { 642 | super(); 643 | } 644 | } 645 | 646 | public static class Criterion { 647 | private String condition; 648 | 649 | private Object value; 650 | 651 | private Object secondValue; 652 | 653 | private boolean noValue; 654 | 655 | private boolean singleValue; 656 | 657 | private boolean betweenValue; 658 | 659 | private boolean listValue; 660 | 661 | private String typeHandler; 662 | 663 | public String getCondition() { 664 | return condition; 665 | } 666 | 667 | public Object getValue() { 668 | return value; 669 | } 670 | 671 | public Object getSecondValue() { 672 | return secondValue; 673 | } 674 | 675 | public boolean isNoValue() { 676 | return noValue; 677 | } 678 | 679 | public boolean isSingleValue() { 680 | return singleValue; 681 | } 682 | 683 | public boolean isBetweenValue() { 684 | return betweenValue; 685 | } 686 | 687 | public boolean isListValue() { 688 | return listValue; 689 | } 690 | 691 | public String getTypeHandler() { 692 | return typeHandler; 693 | } 694 | 695 | protected Criterion(String condition) { 696 | super(); 697 | this.condition = condition; 698 | this.typeHandler = null; 699 | this.noValue = true; 700 | } 701 | 702 | protected Criterion(String condition, Object value, String typeHandler) { 703 | super(); 704 | this.condition = condition; 705 | this.value = value; 706 | this.typeHandler = typeHandler; 707 | if (value instanceof List) { 708 | this.listValue = true; 709 | } else { 710 | this.singleValue = true; 711 | } 712 | } 713 | 714 | protected Criterion(String condition, Object value) { 715 | this(condition, value, null); 716 | } 717 | 718 | protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { 719 | super(); 720 | this.condition = condition; 721 | this.value = value; 722 | this.secondValue = secondValue; 723 | this.typeHandler = typeHandler; 724 | this.betweenValue = true; 725 | } 726 | 727 | protected Criterion(String condition, Object value, Object secondValue) { 728 | this(condition, value, secondValue, null); 729 | } 730 | } 731 | } -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/request/AuthenticationRequest.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean.request; 2 | 3 | import org.hibernate.validator.constraints.NotEmpty; 4 | 5 | /** 6 | * 用户登录参数 7 | * Created by wei. 8 | */ 9 | public class AuthenticationRequest extends CommonRequest{ 10 | @NotEmpty(message = "用户名不能为空") 11 | private String username; 12 | @NotEmpty(message = "密码不能为空") 13 | private String password; 14 | 15 | public String getUsername() { 16 | return username; 17 | } 18 | 19 | public void setUsername(String username) { 20 | this.username = username; 21 | } 22 | 23 | public String getPassword() { 24 | return password; 25 | } 26 | 27 | public void setPassword(String password) { 28 | this.password = password; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "AuthenticationRequest{" + 34 | "username='" + username + '\'' + 35 | ", password='" + password + '\'' + 36 | '}'; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/request/CommonRequest.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean.request; 2 | 3 | /** 4 | * 请求的公共父类 5 | * 6 | * @author 7 | * @create 2019-11-02 9:39 PM 8 | **/ 9 | public class CommonRequest { 10 | } 11 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/user/CustomerInfoReply.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean.user; 2 | 3 | /** 4 | * 登录,刷新token等返回的认证信息 5 | * 6 | * @author 7 | * @create 2019-11-03 8:11 PM 8 | **/ 9 | public class CustomerInfoReply { 10 | 11 | private int reply = 1;//0:实名 1:匿名 12 | 13 | private String token; 14 | 15 | private String refreshToken; 16 | 17 | private Long tokenExpireTime; 18 | 19 | private Long refreshTokenExpireTime; 20 | 21 | private String mobilePhone; 22 | 23 | public CustomerInfoReply(int reply,String token, String refreshToken, 24 | Long tokenExpireTime, Long refreshTokenExpireTime, 25 | String mobilePhone) { 26 | this.token = token; 27 | this.refreshToken = refreshToken; 28 | this.tokenExpireTime = tokenExpireTime; 29 | this.refreshTokenExpireTime = refreshTokenExpireTime; 30 | this.reply = reply; 31 | this.mobilePhone = mobilePhone; 32 | } 33 | 34 | public String getToken() { 35 | return token; 36 | } 37 | 38 | public void setToken(String token) { 39 | this.token = token; 40 | } 41 | 42 | public String getRefreshToken() { 43 | return refreshToken; 44 | } 45 | 46 | public void setRefreshToken(String refreshToken) { 47 | this.refreshToken = refreshToken; 48 | } 49 | 50 | public Long getTokenExpireTime() { 51 | return tokenExpireTime; 52 | } 53 | 54 | public void setTokenExpireTime(Long tokenExpireTime) { 55 | this.tokenExpireTime = tokenExpireTime; 56 | } 57 | 58 | public Long getRefreshTokenExpireTime() { 59 | return refreshTokenExpireTime; 60 | } 61 | 62 | public void setRefreshTokenExpireTime(Long refreshTokenExpireTime) { 63 | this.refreshTokenExpireTime = refreshTokenExpireTime; 64 | } 65 | 66 | @Override 67 | public String toString() { 68 | return "CustomerInfoReply{" + 69 | "token='" + token + '\'' + 70 | ", refreshToken='" + refreshToken + '\'' + 71 | ", tokenExpireTime=" + tokenExpireTime + 72 | ", refreshTokenExpireTime=" + refreshTokenExpireTime + 73 | '}'; 74 | } 75 | 76 | public int getReply() { 77 | return reply; 78 | } 79 | 80 | public void setReply(int reply) { 81 | this.reply = reply; 82 | } 83 | 84 | public String getMobilePhone() { 85 | return mobilePhone; 86 | } 87 | 88 | public void setMobilePhone(String mobilePhone) { 89 | this.mobilePhone = mobilePhone; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/bean/user/JwtUserDetail.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.bean.user; 2 | 3 | import com.tw.cloud.bean.User; 4 | import org.springframework.security.core.GrantedAuthority; 5 | import org.springframework.security.core.userdetails.UserDetails; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * 安全验证的user类 11 | * 12 | * @author 13 | * @create 2019-11-02 3:28 PM 14 | **/ 15 | public class JwtUserDetail implements UserDetails { 16 | 17 | private com.tw.cloud.bean.User mUser; 18 | 19 | 20 | public JwtUserDetail(User user){ 21 | this.mUser = user; 22 | } 23 | 24 | @Override 25 | public Collection getAuthorities() { 26 | return null; 27 | } 28 | 29 | @Override 30 | public String getPassword() { 31 | return mUser.getPassword(); 32 | } 33 | 34 | @Override 35 | public String getUsername() { 36 | return mUser.getId() + ""; 37 | } 38 | 39 | @Override 40 | public boolean isAccountNonExpired() { 41 | return false; 42 | } 43 | 44 | @Override 45 | public boolean isAccountNonLocked() { 46 | return false; 47 | } 48 | 49 | @Override 50 | public boolean isCredentialsNonExpired() { 51 | return false; 52 | } 53 | 54 | @Override 55 | public boolean isEnabled() { 56 | return false; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/component/JwtAuthenticationTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.component; 2 | 3 | import com.tw.cloud.utils.JwtTokenUtil; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 9 | import org.springframework.security.core.context.SecurityContextHolder; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 13 | import org.springframework.web.filter.OncePerRequestFilter; 14 | 15 | import javax.servlet.FilterChain; 16 | import javax.servlet.ServletException; 17 | import javax.servlet.http.HttpServletRequest; 18 | import javax.servlet.http.HttpServletResponse; 19 | import java.io.IOException; 20 | 21 | /** 22 | * JWT登录授权过滤器 23 | * Created by macro on 2018/4/26. 24 | */ 25 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 26 | private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class); 27 | @Autowired 28 | private UserDetailsService userDetailsService; 29 | @Autowired 30 | private JwtTokenUtil jwtTokenUtil; 31 | @Value("${jwt.tokenHeader}") 32 | private String tokenHeader; 33 | @Value("${jwt.tokenHead}") 34 | private String tokenHead; 35 | 36 | @Override 37 | protected void doFilterInternal(HttpServletRequest request, 38 | HttpServletResponse response, 39 | FilterChain chain) throws ServletException, IOException { 40 | String authHeader = request.getHeader(this.tokenHeader); 41 | if (authHeader != null && authHeader.startsWith(this.tokenHead)) { 42 | String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer " 43 | String username = jwtTokenUtil.getUserNameFromToken(authToken); 44 | LOGGER.info("checking username:{}", username); 45 | if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 46 | UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); 47 | if (jwtTokenUtil.validateToken(authToken, userDetails)) { 48 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 49 | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 50 | LOGGER.info("authenticated user:{}", username); 51 | SecurityContextHolder.getContext().setAuthentication(authentication); 52 | } 53 | } 54 | } 55 | chain.doFilter(request, response); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/component/RestAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.component; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.tw.cloud.bean.CommonResp; 5 | import org.springframework.security.core.AuthenticationException; 6 | import org.springframework.security.web.AuthenticationEntryPoint; 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 | * 当未登录或者token失效访问接口时,自定义的返回结果 16 | * Created by macro on 2018/5/14. 17 | */ 18 | @Component 19 | public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { 20 | @Override 21 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { 22 | response.setCharacterEncoding("UTF-8"); 23 | response.setContentType("application/json"); 24 | response.getWriter().println(JSONUtil.parse(CommonResp.unauthorized(authException.getMessage()))); 25 | response.getWriter().flush(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/component/RestfulAccessDeniedHandler.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.component; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.tw.cloud.bean.CommonResp; 5 | import org.springframework.security.access.AccessDeniedException; 6 | import org.springframework.security.web.access.AccessDeniedHandler; 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 | * 当访问接口没有权限时,自定义的返回结果 16 | * Created by macro on 2018/4/26. 17 | */ 18 | @Component 19 | public class RestfulAccessDeniedHandler implements AccessDeniedHandler { 20 | @Override 21 | public void handle(HttpServletRequest request, 22 | HttpServletResponse response, 23 | AccessDeniedException e) throws IOException, ServletException { 24 | response.setCharacterEncoding("UTF-8"); 25 | response.setContentType("application/json"); 26 | response.getWriter().println(JSONUtil.parse(CommonResp.forbidden(e.getMessage()))); 27 | response.getWriter().flush(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/config/MyBatisConfig.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.config; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.transaction.annotation.EnableTransactionManagement; 6 | 7 | /** 8 | * MyBatis配置类 9 | * Created by wei on 2019/4/8. 10 | */ 11 | @Configuration 12 | @EnableTransactionManagement 13 | @MapperScan({"com.tw.cloud.mapper","com.tw.cloud.dao"}) 14 | public class MyBatisConfig { 15 | } 16 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/config/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.config; 2 | 3 | import com.tw.cloud.component.JwtAuthenticationTokenFilter; 4 | import com.tw.cloud.component.RestAuthenticationEntryPoint; 5 | import com.tw.cloud.component.RestfulAccessDeniedHandler; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.http.HttpMethod; 10 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 14 | import org.springframework.security.config.http.SessionCreationPolicy; 15 | import org.springframework.security.core.userdetails.UserDetailsService; 16 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 17 | import org.springframework.security.crypto.password.PasswordEncoder; 18 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 19 | 20 | /** 21 | * 安全控制类 22 | * 23 | * @author 24 | * @create 2019-11-02 3:55 PM 25 | **/ 26 | @Configuration 27 | @EnableWebSecurity 28 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 29 | // Spring会自动寻找同样类型的具体类注入,这里就是JwtUserDetailsServiceImpl了 30 | @Autowired 31 | private UserDetailsService userDetailsService; 32 | @Autowired 33 | private RestfulAccessDeniedHandler restfulAccessDeniedHandler; 34 | @Autowired 35 | private RestAuthenticationEntryPoint restAuthenticationEntryPoint; 36 | 37 | @Autowired 38 | public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 39 | authenticationManagerBuilder 40 | // 设置UserDetailsService 41 | .userDetailsService(this.userDetailsService) 42 | // 使用BCrypt进行密码的hash 43 | .passwordEncoder(passwordEncoder()); 44 | } 45 | // 装载BCrypt密码编码器 46 | @Bean 47 | public PasswordEncoder passwordEncoder() { 48 | return new BCryptPasswordEncoder(); 49 | } 50 | 51 | @Bean 52 | public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){ 53 | return new JwtAuthenticationTokenFilter(); 54 | } 55 | 56 | @Override 57 | protected void configure(HttpSecurity httpSecurity) throws Exception { 58 | httpSecurity 59 | // 由于使用的是JWT,我们这里不需要csrf 60 | .csrf().disable() 61 | 62 | // 基于token,所以不需要session 63 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 64 | 65 | .authorizeRequests() 66 | //.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 67 | 68 | // 允许对于网站静态资源的无授权访问 69 | .antMatchers( 70 | HttpMethod.GET, 71 | "/", 72 | "/*.html", 73 | "/**/*.png", 74 | "/**/*.jpg", 75 | "/favicon.ico", 76 | "/**/*.html", 77 | "/**/*.css", 78 | "/**/*.js" 79 | ).permitAll() 80 | // 对于获取token的rest api要允许匿名访问 81 | .antMatchers("/auth/**").permitAll() 82 | // 除上面外的所有请求全部需要鉴权认证 83 | .anyRequest().authenticated(); 84 | 85 | // 禁用缓存 86 | httpSecurity.headers().cacheControl(); 87 | // 添加JWT filter 88 | httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); 89 | //添加自定义未授权和未登录结果返回 90 | httpSecurity.exceptionHandling() 91 | .accessDeniedHandler(restfulAccessDeniedHandler) 92 | .authenticationEntryPoint(restAuthenticationEntryPoint); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/controller/UmsController.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.controller; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.tw.cloud.bean.CommonResp; 5 | import com.tw.cloud.service.UmsService; 6 | import com.tw.cloud.service.impl.UmsServiceIml; 7 | import com.tw.cloud.utils.UnifyApiUri; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | import org.springframework.web.bind.annotation.RequestParam; 13 | import org.springframework.web.bind.annotation.RestController; 14 | import org.springframework.web.multipart.MultipartFile; 15 | 16 | import java.io.IOException; 17 | import java.nio.file.Files; 18 | import java.nio.file.Path; 19 | import java.nio.file.Paths; 20 | import java.util.UUID; 21 | 22 | /** 23 | * 用户信息操作相关 24 | * 25 | * @author 26 | * @create 2020-02-05 4:10 PM 27 | **/ 28 | @RestController 29 | public class UmsController { 30 | 31 | @Autowired 32 | private UmsService umsService; 33 | 34 | 35 | @RequestMapping(value = UnifyApiUri.UserApi.API_UPLOAD_GALLERY, 36 | method = RequestMethod.POST, produces = MediaType.MULTIPART_FORM_DATA_VALUE) 37 | public String uploadGallery(@RequestParam("file") MultipartFile file) { 38 | if (file.isEmpty()) { 39 | return JSONUtil.parse(CommonResp.failed("file can not null")).toStringPretty(); 40 | } 41 | // Get the file and save it somewhere 42 | return umsService.uploadGallery(file); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.controller; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.tw.cloud.bean.User; 5 | import com.tw.cloud.bean.request.AuthenticationRequest; 6 | import com.tw.cloud.bean.user.CustomerInfoReply; 7 | import com.tw.cloud.service.UserService; 8 | import com.tw.cloud.utils.ResultCode; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.beans.factory.annotation.Value; 13 | import org.springframework.http.MediaType; 14 | import org.springframework.web.bind.annotation.*; 15 | import com.tw.cloud.bean.CommonResp; 16 | import com.tw.cloud.utils.Constants; 17 | import com.tw.cloud.utils.UnifyApiUri; 18 | import org.springframework.web.multipart.MultipartFile; 19 | 20 | import java.io.IOException; 21 | import java.nio.file.Files; 22 | import java.nio.file.Path; 23 | import java.nio.file.Paths; 24 | import java.util.UUID; 25 | 26 | /** 27 | * 用户相关controller 28 | * 29 | * @author 30 | * @create 2019-10-20 7:50 PM 31 | **/ 32 | @RestController 33 | public class UserController { 34 | private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class); 35 | 36 | @Autowired 37 | private UserService mUserService; 38 | 39 | @Value("${file.UPLOADED_FOLDER}") 40 | private String UPLOADED_FOLDER; 41 | @Value("${file.UPLOADED_PATH}") 42 | private String UPLOADED_PATH; 43 | 44 | 45 | @RequestMapping(value = UnifyApiUri.UserApi.API_CUSTOMER_INFO, method = RequestMethod.GET) 46 | public CommonResp getCustomerInfo() { 47 | LOGGER.info("getCustomerInfo"); 48 | com.tw.cloud.bean.User user = mUserService.getCustomerInfo(); 49 | if (user != null) { 50 | return CommonResp.success(user); 51 | } else { 52 | return new CommonResp(Constants.RESULT_ERROR, ResultCode.RESULT_CODE_1002.getCode() 53 | , ResultCode.RESULT_CODE_1002.getMessage(), null); 54 | } 55 | } 56 | 57 | @RequestMapping(value = UnifyApiUri.UserApi.API_AUTH_LOGIN, 58 | method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 59 | public CommonResp login(@RequestBody AuthenticationRequest authenticationRequest) { 60 | LOGGER.info("login info==>" + authenticationRequest.toString()); 61 | CustomerInfoReply customerInfoReply = mUserService.login(authenticationRequest.getUsername(), authenticationRequest.getPassword()); 62 | LOGGER.info("customerInfoReply info==>" + customerInfoReply.toString()); 63 | return CommonResp.success(customerInfoReply); 64 | } 65 | 66 | @RequestMapping(value = UnifyApiUri.UserApi.API_AUTH_REGISTER, 67 | method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 68 | public CommonResp register(@RequestBody AuthenticationRequest authenticationRequest) { 69 | LOGGER.info("register info==>" + authenticationRequest.toString()); 70 | CustomerInfoReply customerInfoReply = mUserService.register(authenticationRequest.getUsername(), authenticationRequest.getPassword()); 71 | LOGGER.info("customerInfoReply info==>" + customerInfoReply.toString()); 72 | return CommonResp.success(customerInfoReply); 73 | } 74 | 75 | @RequestMapping(value = UnifyApiUri.UserApi.API_AUTH_SEND_MOBILE_PHONE_CODE, 76 | method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 77 | public CommonResp sendMobileCode(@RequestParam("mobilePhone") String mobilePhone) { 78 | LOGGER.info("sendMobileCode info==>" + mobilePhone); 79 | mUserService.sendMobileCode(mobilePhone); 80 | return CommonResp.success(null); 81 | } 82 | 83 | @RequestMapping(value = UnifyApiUri.UserApi.API_AUTH_LOGIN_BY_PHONE, 84 | method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 85 | public CommonResp loginByPhone(@RequestParam("mobilePhone") String mobilePhone,@RequestParam("verifyCode") String verifyCode) { 86 | LOGGER.info("loginByPhone info==>" + mobilePhone + "--verifyCode==",verifyCode); 87 | return mUserService.loginByPhone(mobilePhone,verifyCode); 88 | } 89 | 90 | @RequestMapping(value = UnifyApiUri.UserApi.API_UPDATE_CUSTOMER_INFO, 91 | method = RequestMethod.POST, produces = MediaType.MULTIPART_FORM_DATA_VALUE) 92 | public String updateCustomerInfo(@RequestParam("file") MultipartFile file) { 93 | if (file.isEmpty()) { 94 | return JSONUtil.parse(CommonResp.failed("file can not null")).toStringPretty(); 95 | } 96 | // Get the file and save it somewhere 97 | try { 98 | byte[] bytes = file.getBytes(); 99 | String tempUrl = UUID.randomUUID() + file.getOriginalFilename(); 100 | String pathString = UPLOADED_FOLDER + tempUrl; 101 | Path path = Paths.get(pathString); 102 | Files.write(path, bytes); 103 | mUserService.updateUserHeader(UPLOADED_PATH + tempUrl); 104 | return JSONUtil.parse(CommonResp.success("result is ok")).toStringPretty(); 105 | } catch (IOException e) { 106 | e.printStackTrace(); 107 | return JSONUtil.parse(CommonResp.failed(e.getMessage())).toStringPretty(); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/mapper/UmsGalleryMapper.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.mapper; 2 | 3 | import com.tw.cloud.bean.UmsGallery; 4 | import com.tw.cloud.bean.UmsGalleryExample; 5 | import java.util.List; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | public interface UmsGalleryMapper { 9 | int countByExample(UmsGalleryExample example); 10 | 11 | int deleteByExample(UmsGalleryExample example); 12 | 13 | int deleteByPrimaryKey(Integer id); 14 | 15 | int insert(UmsGallery record); 16 | 17 | int insertSelective(UmsGallery record); 18 | 19 | List selectByExampleWithBLOBs(UmsGalleryExample example); 20 | 21 | List selectByExample(UmsGalleryExample example); 22 | 23 | UmsGallery selectByPrimaryKey(Integer id); 24 | 25 | int updateByExampleSelective(@Param("record") UmsGallery record, @Param("example") UmsGalleryExample example); 26 | 27 | int updateByExampleWithBLOBs(@Param("record") UmsGallery record, @Param("example") UmsGalleryExample example); 28 | 29 | int updateByExample(@Param("record") UmsGallery record, @Param("example") UmsGalleryExample example); 30 | 31 | int updateByPrimaryKeySelective(UmsGallery record); 32 | 33 | int updateByPrimaryKeyWithBLOBs(UmsGallery record); 34 | 35 | int updateByPrimaryKey(UmsGallery record); 36 | } -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.mapper; 2 | 3 | import com.tw.cloud.bean.User; 4 | import com.tw.cloud.bean.UserExample; 5 | import java.util.List; 6 | import org.apache.ibatis.annotations.Param; 7 | 8 | public interface UserMapper { 9 | int countByExample(UserExample example); 10 | 11 | int deleteByExample(UserExample example); 12 | 13 | int deleteByPrimaryKey(Integer id); 14 | 15 | int insert(User record); 16 | 17 | int insertSelective(User record); 18 | 19 | List selectByExample(UserExample example); 20 | 21 | User selectByPrimaryKey(Integer id); 22 | 23 | int updateByExampleSelective(@Param("record") User record, @Param("example") UserExample example); 24 | 25 | int updateByExample(@Param("record") User record, @Param("example") UserExample example); 26 | 27 | int updateByPrimaryKeySelective(User record); 28 | 29 | int updateByPrimaryKey(User record); 30 | } -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/service/RedisService.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.service; 2 | 3 | /** 4 | * redis操作Service, 5 | * 对象和数组都以json形式进行存储 6 | * Created by wei on 2019/8/7. 7 | */ 8 | public interface RedisService { 9 | /** 10 | * 存储数据 11 | */ 12 | void set(String key, String value); 13 | 14 | /** 15 | * 获取数据 16 | */ 17 | String get(String key); 18 | 19 | /** 20 | * 设置超期时间 21 | */ 22 | boolean expire(String key, long expire); 23 | 24 | /** 25 | * 删除数据 26 | */ 27 | void remove(String key); 28 | 29 | /** 30 | * 自增操作 31 | * @param delta 自增步长 32 | */ 33 | Long increment(String key, long delta); 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/service/UmsService.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.service; 2 | 3 | import com.tw.cloud.bean.CommonResp; 4 | import org.springframework.web.multipart.MultipartFile; 5 | 6 | public interface UmsService { 7 | 8 | String uploadGallery(MultipartFile multipartFile); 9 | } 10 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.service; 2 | 3 | import com.tw.cloud.bean.CommonResp; 4 | import com.tw.cloud.bean.User; 5 | import com.tw.cloud.bean.user.CustomerInfoReply; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | 8 | /** 9 | * 用户相关操作 10 | * 11 | * @author 12 | * @create 2019-11-02 8:45 PM 13 | **/ 14 | public interface UserService { 15 | 16 | String register(); 17 | 18 | CustomerInfoReply login(String username, String password); 19 | 20 | CustomerInfoReply register(String username, String password); 21 | 22 | void updateUserHeader(String headUrl); 23 | 24 | User getCustomerInfo(); 25 | 26 | UserDetails getUserDetails(); 27 | 28 | 29 | void sendMobileCode(String mobilePhone); 30 | 31 | CommonResp loginByPhone(String telephone, String authCode); 32 | 33 | //刷新token 34 | String refresh(String refreshToken); 35 | } 36 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/service/impl/RedisServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.service.impl; 2 | 3 | import com.tw.cloud.service.RedisService; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.data.redis.core.StringRedisTemplate; 6 | import org.springframework.stereotype.Service; 7 | 8 | import java.util.concurrent.TimeUnit; 9 | 10 | /** 11 | * redis操作Service的实现类 12 | * Created by wei on 2019/8/7. 13 | */ 14 | @Service 15 | public class RedisServiceImpl implements RedisService { 16 | @Autowired 17 | private StringRedisTemplate stringRedisTemplate; 18 | 19 | @Override 20 | public void set(String key, String value) { 21 | stringRedisTemplate.opsForValue().set(key, value); 22 | } 23 | 24 | @Override 25 | public String get(String key) { 26 | return stringRedisTemplate.opsForValue().get(key); 27 | } 28 | 29 | @Override 30 | public boolean expire(String key, long expire) { 31 | return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS); 32 | } 33 | 34 | @Override 35 | public void remove(String key) { 36 | stringRedisTemplate.delete(key); 37 | } 38 | 39 | @Override 40 | public Long increment(String key, long delta) { 41 | return stringRedisTemplate.opsForValue().increment(key,delta); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/service/impl/UmsServiceIml.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.service.impl; 2 | 3 | import cn.hutool.json.JSONUtil; 4 | import com.tw.cloud.bean.CommonResp; 5 | import com.tw.cloud.bean.UmsGallery; 6 | import com.tw.cloud.bean.UmsGalleryExample; 7 | import com.tw.cloud.mapper.UmsGalleryMapper; 8 | import com.tw.cloud.service.UmsService; 9 | import com.tw.cloud.utils.JwtTokenUtil; 10 | import com.tw.common.utils.NetworkUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.beans.factory.annotation.Value; 15 | import org.springframework.security.core.userdetails.UserDetails; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.web.multipart.MultipartFile; 18 | 19 | import java.io.IOException; 20 | import java.nio.file.Files; 21 | import java.nio.file.Path; 22 | import java.nio.file.Paths; 23 | import java.util.Date; 24 | import java.util.UUID; 25 | 26 | /** 27 | * 用户信息相关service 28 | * 29 | * @author 30 | * @create 2020-02-05 4:13 PM 31 | **/ 32 | @Service 33 | public class UmsServiceIml implements UmsService { 34 | 35 | private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); 36 | 37 | @Autowired 38 | UmsGalleryMapper umsGalleryMapper; 39 | 40 | @Value("${file.UPLOADED_FOLDER}") 41 | private String UPLOADED_FOLDER; 42 | @Value("${file.UPLOADED_PATH}") 43 | private String UPLOADED_PATH; 44 | 45 | @Value("${server.port}") 46 | private String port; 47 | 48 | @Override 49 | public String uploadGallery(MultipartFile file) { 50 | try { 51 | UserDetails userDetails = JwtTokenUtil.getUserDetails(); 52 | byte[] bytes = file.getBytes(); 53 | String tempUrl = UUID.randomUUID() + file.getOriginalFilename(); 54 | String pathString = UPLOADED_FOLDER + tempUrl; 55 | Path path = Paths.get(pathString); 56 | Files.write(path, bytes); 57 | UmsGallery umsGallery = new UmsGallery(); 58 | umsGallery.setCreateTime(new Date()); 59 | umsGallery.setUserId(Integer.parseInt(userDetails.getUsername())); 60 | umsGallery.setUrl("http://" + NetworkUtils.getLocalHost() + ":" + port + UPLOADED_PATH + tempUrl); 61 | umsGalleryMapper.insert(umsGallery); 62 | return JSONUtil.parse(CommonResp.success(umsGallery.getUrl())).toStringPretty(); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | return JSONUtil.parse(CommonResp.failed(e.getMessage())).toStringPretty(); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/service/impl/UserDetailServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.service.impl; 2 | 3 | import com.tw.cloud.bean.user.JwtUserDetail; 4 | import com.tw.cloud.mapper.UserMapper; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.security.core.userdetails.UserDetails; 7 | import org.springframework.security.core.userdetails.UserDetailsService; 8 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * 用户服务类 13 | * 14 | * @author 15 | * @create 2019-11-02 8:42 PM 16 | **/ 17 | @Service 18 | public class UserDetailServiceImpl implements UserDetailsService { 19 | 20 | @Autowired 21 | private UserMapper mUserMapper; 22 | 23 | /** 24 | * 此处username直接使用用户id 25 | * @param username 26 | * @return 27 | * @throws UsernameNotFoundException 28 | */ 29 | @Override 30 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 31 | com.tw.cloud.bean.User user = mUserMapper.selectByPrimaryKey(Integer.parseInt(username)); 32 | if (user != null) { 33 | return new JwtUserDetail(user); 34 | } 35 | throw new UsernameNotFoundException("用户名或密码错误"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.service.impl; 2 | 3 | import com.tw.cloud.bean.CommonResp; 4 | import com.tw.cloud.bean.User; 5 | import com.tw.cloud.bean.UserExample; 6 | import com.tw.cloud.bean.user.CustomerInfoReply; 7 | import com.tw.cloud.controller.UserController; 8 | import com.tw.cloud.mapper.UserMapper; 9 | import com.tw.cloud.service.RedisService; 10 | import com.tw.cloud.service.UserService; 11 | import com.tw.cloud.utils.JwtTokenUtil; 12 | import com.tw.common.utils.StringUtils; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.beans.factory.annotation.Value; 17 | import org.springframework.security.authentication.BadCredentialsException; 18 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 19 | import org.springframework.security.core.Authentication; 20 | import org.springframework.security.core.context.SecurityContext; 21 | import org.springframework.security.core.context.SecurityContextHolder; 22 | import org.springframework.security.core.userdetails.UserDetails; 23 | import org.springframework.security.core.userdetails.UserDetailsService; 24 | import org.springframework.security.crypto.password.PasswordEncoder; 25 | import org.springframework.stereotype.Service; 26 | 27 | import java.util.Date; 28 | import java.util.List; 29 | 30 | /** 31 | * 用户服务实现类 32 | * 33 | * @author 34 | * @create 2019-11-01 9:46 PM 35 | **/ 36 | @Service 37 | public class UserServiceImpl implements UserService { 38 | 39 | private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class); 40 | 41 | 42 | @Autowired 43 | private UserDetailsService mUserDetailsService; 44 | 45 | @Autowired 46 | private PasswordEncoder mPasswordEncoder; 47 | 48 | @Autowired 49 | private JwtTokenUtil mJwtTokenUtil; 50 | 51 | @Autowired 52 | private UserMapper mUserMapper; 53 | 54 | 55 | @Value("${jwt.expiration}") 56 | private Long mExpiration; 57 | @Value("${jwt.expirationRefreshToken}") 58 | private Long mExpirationRefreshToken; 59 | 60 | @Autowired 61 | private RedisService redisService; 62 | @Value("${redis.key.prefix.authCode}") 63 | private String REDIS_KEY_PREFIX_AUTH_CODE; 64 | @Value("${redis.key.expire.authCode}") 65 | private Long AUTH_CODE_EXPIRE_SECONDS; 66 | 67 | 68 | @Override 69 | public String register() { 70 | return null; 71 | } 72 | 73 | @Override 74 | public CustomerInfoReply login(String username, String password) { 75 | UserDetails userDetails = mUserDetailsService.loadUserByUsername(username); 76 | if (!mPasswordEncoder.matches(password, userDetails.getPassword())) { 77 | throw new BadCredentialsException("密码不正确"); 78 | } 79 | // if(!password.equals(userDetails.getPassword())){ 80 | // throw new BadCredentialsException("密码不正确"); 81 | // } 82 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 83 | SecurityContextHolder.getContext().setAuthentication(authentication); 84 | String token = mJwtTokenUtil.generateToken(userDetails); 85 | String refreshToken = mJwtTokenUtil.generateRefreshToken(userDetails); 86 | return new CustomerInfoReply(0,token, refreshToken, mExpiration, mExpirationRefreshToken,userDetails.getUsername()); 87 | } 88 | 89 | @Override 90 | public CustomerInfoReply register(String username, String password) { 91 | // User umsAdmin = new User(); 92 | // umsAdmin.setLoginName(username); 93 | // umsAdmin.setCreateTime(new Date()); 94 | // //TODO 查询是否有相同用户名的用户 95 | // //将密码进行加密操作 96 | // String encodePassword = mPasswordEncoder.encode(password); 97 | // umsAdmin.setPassword(encodePassword); 98 | // int count = mUserMapper.insert(umsAdmin); 99 | return null; 100 | } 101 | 102 | @Override 103 | public void updateUserHeader(String headUrl) { 104 | UserDetails user = getUserDetails(); 105 | 106 | // mUserMapper.updateUserHeader(user.getUsername(), headUrl); 107 | } 108 | 109 | @Override 110 | public User getCustomerInfo() { 111 | UserDetails user = getUserDetails(); 112 | return null; 113 | // return mUserMapper.selectUserByLoginName(user.getUsername()); 114 | } 115 | 116 | @Override 117 | public UserDetails getUserDetails() { 118 | SecurityContext ctx = SecurityContextHolder.getContext(); 119 | Authentication auth = ctx.getAuthentication(); 120 | UserDetails userDetails = (UserDetails) auth.getPrincipal(); 121 | return userDetails; 122 | } 123 | 124 | @Override 125 | public void sendMobileCode(String mobilePhone) { 126 | String code = StringUtils.randomCode(); 127 | LOGGER.info("MobilePhone:" + mobilePhone + "---code==" + code); 128 | //验证码绑定手机号并存储到redis 129 | redisService.set(REDIS_KEY_PREFIX_AUTH_CODE + mobilePhone, code); 130 | redisService.expire(REDIS_KEY_PREFIX_AUTH_CODE + mobilePhone, AUTH_CODE_EXPIRE_SECONDS); 131 | } 132 | 133 | @Override 134 | public CommonResp loginByPhone(String telephone, String authCode) { 135 | //验证验证码 136 | if (!verifyAuthCode(authCode, telephone)) { 137 | return CommonResp.failed("验证码错误"); 138 | } 139 | UserExample userExample = new UserExample(); 140 | userExample.createCriteria().andMobilephoneEqualTo(telephone); 141 | 142 | List userList = mUserMapper.selectByExample(userExample); 143 | 144 | String id = ""; 145 | if (userList != null && userList.size() > 0) { 146 | com.tw.cloud.bean.User user = userList.get(0); 147 | user.setLogintime(new Date()); 148 | id = user.getId() + ""; 149 | mUserMapper.updateByPrimaryKey(user); 150 | } else { 151 | com.tw.cloud.bean.User user = new com.tw.cloud.bean.User(); 152 | Date date = new Date(); 153 | user.setCreatetime(date); 154 | user.setLogintime(date); 155 | user.setMobilephone(telephone); 156 | user.setLoginname(telephone); 157 | user.setPassword(mPasswordEncoder.encode(telephone)); 158 | id = mUserMapper.insertSelective(user) + ""; 159 | LOGGER.info("result==",id); 160 | } 161 | UserDetails userDetails = mUserDetailsService.loadUserByUsername(id); 162 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 163 | SecurityContextHolder.getContext().setAuthentication(authentication); 164 | String token = mJwtTokenUtil.generateToken(userDetails); 165 | String refreshToken = mJwtTokenUtil.generateRefreshToken(userDetails); 166 | return CommonResp.success(new CustomerInfoReply(0,token, refreshToken, 167 | mExpiration, mExpirationRefreshToken,telephone), "登录成功"); 168 | } 169 | 170 | 171 | //对输入的验证码进行校验 172 | private boolean verifyAuthCode(String authCode, String telephone) { 173 | if (org.springframework.util.StringUtils.isEmpty(authCode)) { 174 | return false; 175 | } 176 | String realAuthCode = redisService.get(REDIS_KEY_PREFIX_AUTH_CODE + telephone); 177 | return authCode.equals(realAuthCode); 178 | } 179 | 180 | @Override 181 | public String refresh(String refreshToken) { 182 | return null; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/utils/Constants.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.utils; 2 | 3 | /** 4 | * 变量配置类 5 | * 6 | * @author 7 | * @create 2019-10-20 5:12 PM 8 | **/ 9 | public class Constants { 10 | 11 | /** 12 | * 返回成功 13 | */ 14 | public static final int RESULT_OK = 0; 15 | /** 16 | * 返回失败 17 | */ 18 | public static final int RESULT_ERROR = 1; 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/utils/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.utils; 2 | 3 | /** 4 | * 错误码声明类 5 | */ 6 | public class ErrorCode { 7 | 8 | public static final String ERROR_CODE_1001 = "1001"; 9 | public static final String ERROR_CODE_1002 = "1002"; 10 | public static final String ERROR_CODE_1003 = "1003"; 11 | public static final String ERROR_CODE_1004 = "1004"; 12 | public static final String ERROR_CODE_1005 = "1005"; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/utils/IErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.utils; 2 | 3 | /** 4 | * 封装API的错误码 5 | * Created by macro on 2019/4/19. 6 | */ 7 | public interface IErrorCode { 8 | String getCode(); 9 | 10 | String getMessage(); 11 | } 12 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/utils/JwtTokenUtil.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.utils; 2 | 3 | import io.jsonwebtoken.*; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.security.core.context.SecurityContext; 9 | import org.springframework.security.core.context.SecurityContextHolder; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.stereotype.Component; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import java.util.Date; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | /** 19 | * JwtToken生成的工具类 20 | * JWT token的格式:header.payload.signature 21 | * header的格式(算法、token的类型): 22 | * {"alg": "HS512","typ": "JWT"} 23 | * payload的格式(用户名、创建时间、生成时间): 24 | * {"sub":"wang","created":1489079981393,"exp":1489684781} 25 | * signature的生成算法: 26 | * HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret) 27 | * Created by wei 28 | */ 29 | @Component 30 | public class JwtTokenUtil { 31 | private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class); 32 | private static final String CLAIM_KEY_CREATED = "created"; 33 | @Value("${jwt.secret}") 34 | private String secret; 35 | @Value("${jwt.expiration}") 36 | private Long expiration; 37 | @Value("${jwt.expirationRefreshToken}") 38 | private Long expirationRefreshToken; 39 | @Value("${jwt.tokenHeader}") 40 | private String tokenHeader; 41 | @Value("${jwt.tokenHead}") 42 | private String tokenHead; 43 | 44 | /** 45 | * 根据负责生成JWT的token 46 | */ 47 | private String generateToken(Map claims) { 48 | return Jwts.builder() 49 | .setClaims(claims) 50 | .setExpiration(generateExpirationDate()) 51 | .signWith(SignatureAlgorithm.HS512, secret) 52 | .compact(); 53 | } 54 | 55 | /** 56 | * 根据负责生成JWT的refreshToken 57 | */ 58 | private String generateRefreshToken(Map claims) { 59 | return Jwts.builder() 60 | .setClaims(claims) 61 | .setExpiration(generateRefreshTokenExpirationDate()) 62 | .signWith(SignatureAlgorithm.HS512, secret) 63 | .compact(); 64 | } 65 | 66 | /** 67 | * 从token中获取JWT中的负载 68 | */ 69 | private Claims getClaimsFromToken(String token) { 70 | Claims claims = null; 71 | try { 72 | claims = Jwts.parser() 73 | .setSigningKey(secret) 74 | .parseClaimsJws(token) 75 | .getBody(); 76 | } catch (Exception e) { 77 | LOGGER.info("JWT格式验证失败:{}", token); 78 | } 79 | return claims; 80 | } 81 | 82 | /** 83 | * 生成token的过期时间 84 | */ 85 | private Date generateExpirationDate() { 86 | return new Date(System.currentTimeMillis() + expiration * 1000); 87 | } 88 | 89 | /** 90 | * 生成refreshToken的过期时间 91 | */ 92 | private Date generateRefreshTokenExpirationDate() { 93 | return new Date(System.currentTimeMillis() + expirationRefreshToken * 1000); 94 | } 95 | 96 | /** 97 | * 从token中获取登录用户名 98 | */ 99 | public String getUserNameFromToken(String token) { 100 | String username; 101 | try { 102 | Claims claims = getClaimsFromToken(token); 103 | username = claims.getSubject(); 104 | } catch (Exception e) { 105 | username = null; 106 | } 107 | return username; 108 | } 109 | 110 | /** 111 | * 验证token是否还有效 112 | * 113 | * @param token 客户端传入的token 114 | * @param userDetails 从数据库中查询出来的用户信息 115 | */ 116 | public boolean validateToken(String token, UserDetails userDetails) { 117 | String username = getUserNameFromToken(token); 118 | return username.equals(userDetails.getUsername()) && !isTokenExpired(token); 119 | } 120 | 121 | /** 122 | * 判断token是否已经失效 123 | */ 124 | private boolean isTokenExpired(String token) { 125 | Date expiredDate = getExpiredDateFromToken(token); 126 | return expiredDate.before(new Date()); 127 | } 128 | 129 | /** 130 | * 从token中获取过期时间 131 | */ 132 | private Date getExpiredDateFromToken(String token) { 133 | Claims claims = getClaimsFromToken(token); 134 | return claims.getExpiration(); 135 | } 136 | 137 | /** 138 | * 根据用户信息生成token 139 | */ 140 | public String generateToken(UserDetails userDetails) { 141 | Map claims = new HashMap<>(); 142 | claims.put(Claims.SUBJECT, userDetails.getUsername()); 143 | claims.put(CLAIM_KEY_CREATED, new Date()); 144 | return generateToken(claims); 145 | } 146 | 147 | /** 148 | * 根据用户信息生成token 149 | */ 150 | public String generateRefreshToken(UserDetails userDetails) { 151 | Map claims = new HashMap<>(); 152 | claims.put(Claims.SUBJECT, userDetails.getUsername()); 153 | claims.put(CLAIM_KEY_CREATED, new Date()); 154 | return generateRefreshToken(claims); 155 | } 156 | 157 | /** 158 | * 判断token是否可以被刷新 159 | */ 160 | public boolean canRefresh(String token) { 161 | return !isTokenExpired(token); 162 | } 163 | 164 | /** 165 | * 刷新token 166 | */ 167 | public String refreshToken(String token) { 168 | Claims claims = getClaimsFromToken(token); 169 | claims.put(CLAIM_KEY_CREATED, new Date()); 170 | return generateToken(claims); 171 | } 172 | 173 | public String getLoginNameFromHttpServer(HttpServletRequest request) { 174 | String authHeader = request.getHeader(this.tokenHeader); 175 | if (authHeader != null && authHeader.startsWith(this.tokenHead)) { 176 | String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer " 177 | return getUserNameFromToken(authToken); 178 | } 179 | return ""; 180 | } 181 | 182 | public static UserDetails getUserDetails() { 183 | SecurityContext ctx = SecurityContextHolder.getContext(); 184 | Authentication auth = ctx.getAuthentication(); 185 | UserDetails userDetails = (UserDetails) auth.getPrincipal(); 186 | return userDetails; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/utils/ResultCode.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.utils; 2 | 3 | /** 4 | * 5 | */ 6 | public enum ResultCode implements IErrorCode { 7 | 8 | RESULT_CODE_1001(ErrorCode.ERROR_CODE_1001, ""), 9 | RESULT_CODE_1002(ErrorCode.ERROR_CODE_1002, "操作失败"), 10 | RESULT_CODE_1003(ErrorCode.ERROR_CODE_1003, "参数检验失败"), 11 | RESULT_CODE_1004(ErrorCode.ERROR_CODE_1004, "暂未登录或token已经过期"), 12 | RESULT_CODE_1005(ErrorCode.ERROR_CODE_1005, "没有相关权限"); 13 | 14 | private String code; 15 | private String message; 16 | 17 | private ResultCode(String code, String message) { 18 | this.code = code; 19 | this.message = message; 20 | } 21 | 22 | public String getCode() { 23 | return code; 24 | } 25 | 26 | public String getMessage() { 27 | return message; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Code/src/main/java/com/tw/cloud/utils/UnifyApiUri.java: -------------------------------------------------------------------------------- 1 | package com.tw.cloud.utils; 2 | 3 | /** 4 | * 所有接口地址类 5 | * 6 | * @author 7 | * @create 2019-10-20 7:55 PM 8 | **/ 9 | public class UnifyApiUri { 10 | 11 | public static class UserApi { 12 | public static final String API_CUSTOMER_BASE = "/user"; 13 | public static final String API_CUSTOMER_INFO = API_CUSTOMER_BASE + "/getCustomerInfo"; 14 | public static final String API_UPDATE_CUSTOMER_INFO = API_CUSTOMER_BASE + "/updateCustomerInfo"; 15 | public static final String API_UPLOAD_GALLERY = API_CUSTOMER_BASE + "/uploadGallery"; 16 | 17 | 18 | 19 | public static final String API_AUTH_BASE = "/auth"; 20 | public static final String API_AUTH_LOGIN = API_AUTH_BASE + "/login"; 21 | public static final String API_AUTH_REGISTER = API_AUTH_BASE + "/register"; 22 | public static final String API_AUTH_SEND_MOBILE_PHONE_CODE = API_AUTH_BASE + "/sendMobileCode"; 23 | public static final String API_AUTH_LOGIN_BY_PHONE = API_AUTH_BASE + "/login_by_phone"; 24 | public static final String API_AUTH_REFRESH_TOKEN = API_AUTH_BASE + "/refresh_token"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Code/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | profiles: 3 | active: dev #默认为开发环境 4 | datasource: 5 | #mysql数据库 6 | url: jdbc:mysql://localhost:3306/springflutter 7 | #数据库用户名 8 | username: root 9 | #密码 10 | password: wei@989322 11 | mysqllocation: mysql-connector-java-8.0.11.jar 12 | type: com.alibaba.druid.pool.DruidDataSource 13 | druid: 14 | initial-size: 5 #连接池初始化大小 15 | min-idle: 10 #最小空闲连接数 16 | max-active: 20 #最大连接数 17 | web-stat-filter: 18 | exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" #不统计这些请求数据 19 | stat-view-servlet: #访问监控网页的登录用户名和密码 20 | login-username: druid 21 | login-password: druid 22 | mvc: 23 | static-path-pattern: /images/** 24 | resources: 25 | static-locations: file:///System/Volumes/Data/my_computer/project/spring_flutter/image 26 | servlet: 27 | multipart: 28 | enabled: true #开启文件上传 29 | max-file-size: 10MB #限制文件上传大小为10M 30 | server: 31 | port: 8089 #服务运行端口 32 | 33 | mybatis: 34 | mapper-locations: 35 | - classpath:mapper/*.xml #mybatis 对应的mapper路径 36 | 37 | jwt: 38 | tokenHeader: Authorization #JWT存储的请求头 39 | secret: mySecret #JWT加解密使用的密钥 40 | expiration: 259200 #JWT的超期限时间(60*60*24*3) 41 | expirationRefreshToken: 54432000 #JWT的超期限时间(60*60*24*90) 42 | tokenHead: Bearer #JWT负载中拿到开头 43 | file: 44 | UPLOADED_FOLDER: /System/Volumes/Data/my_computer/project/spring_flutter/image/ 45 | UPLOADED_PATH: /images/ 46 | logging: 47 | level: 48 | root: info #日志配置DEBUG,INFO,WARN,ERROR 49 | # file: demo_log.log #配置日志生成路径 50 | # path: /var/logs #配置日志文件名称 51 | 52 | redis: 53 | host: localhost # Redis服务器地址 54 | database: 0 # Redis数据库索引(默认为0) 55 | port: 6379 # Redis服务器连接端口 56 | password: # Redis服务器连接密码(默认为空) 57 | jedis: 58 | pool: 59 | max-active: 8 # 连接池最大连接数(使用负值表示没有限制) 60 | max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) 61 | max-idle: 8 # 连接池中的最大空闲连接 62 | min-idle: 0 # 连接池中的最小空闲连接 63 | timeout: 3000ms # 连接超时时间(毫秒) 64 | key: 65 | prefix: 66 | authCode: "portal:authCode:" 67 | expire: 68 | authCode: 300 # 验证码超期时间 69 | 70 | -------------------------------------------------------------------------------- /Code/src/main/resources/generator.properties: -------------------------------------------------------------------------------- 1 | jdbc.driverClass=com.mysql.cj.jdbc.Driver 2 | jdbc.connectionURL=jdbc:mysql://localhost:3306/springflutter?useUnicode=true&characterEncoding=utf-8 3 | jdbc.userId=root 4 | jdbc.password=wei@989322 -------------------------------------------------------------------------------- /Code/src/main/resources/generatorConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 37 | 38 | 39 | 40 |
41 |
42 |
-------------------------------------------------------------------------------- /Code/src/main/resources/mapper/UmsGalleryMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | and ${criterion.condition} 23 | 24 | 25 | and ${criterion.condition} #{criterion.value} 26 | 27 | 28 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 29 | 30 | 31 | and ${criterion.condition} 32 | 33 | #{listItem} 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | and ${criterion.condition} 52 | 53 | 54 | and ${criterion.condition} #{criterion.value} 55 | 56 | 57 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 58 | 59 | 60 | and ${criterion.condition} 61 | 62 | #{listItem} 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | id, user_id, name, url, create_time 74 | 75 | 76 | description 77 | 78 | 94 | 108 | 116 | 117 | delete from ums_gallery 118 | where id = #{id,jdbcType=INTEGER} 119 | 120 | 121 | delete from ums_gallery 122 | 123 | 124 | 125 | 126 | 127 | 128 | SELECT LAST_INSERT_ID() 129 | 130 | insert into ums_gallery (user_id, name, url, 131 | create_time, description) 132 | values (#{userId,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{url,jdbcType=VARCHAR}, 133 | #{createTime,jdbcType=TIMESTAMP}, #{description,jdbcType=LONGVARCHAR}) 134 | 135 | 136 | 137 | SELECT LAST_INSERT_ID() 138 | 139 | insert into ums_gallery 140 | 141 | 142 | user_id, 143 | 144 | 145 | name, 146 | 147 | 148 | url, 149 | 150 | 151 | create_time, 152 | 153 | 154 | description, 155 | 156 | 157 | 158 | 159 | #{userId,jdbcType=INTEGER}, 160 | 161 | 162 | #{name,jdbcType=VARCHAR}, 163 | 164 | 165 | #{url,jdbcType=VARCHAR}, 166 | 167 | 168 | #{createTime,jdbcType=TIMESTAMP}, 169 | 170 | 171 | #{description,jdbcType=LONGVARCHAR}, 172 | 173 | 174 | 175 | 181 | 182 | update ums_gallery 183 | 184 | 185 | id = #{record.id,jdbcType=INTEGER}, 186 | 187 | 188 | user_id = #{record.userId,jdbcType=INTEGER}, 189 | 190 | 191 | name = #{record.name,jdbcType=VARCHAR}, 192 | 193 | 194 | url = #{record.url,jdbcType=VARCHAR}, 195 | 196 | 197 | create_time = #{record.createTime,jdbcType=TIMESTAMP}, 198 | 199 | 200 | description = #{record.description,jdbcType=LONGVARCHAR}, 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | update ums_gallery 209 | set id = #{record.id,jdbcType=INTEGER}, 210 | user_id = #{record.userId,jdbcType=INTEGER}, 211 | name = #{record.name,jdbcType=VARCHAR}, 212 | url = #{record.url,jdbcType=VARCHAR}, 213 | create_time = #{record.createTime,jdbcType=TIMESTAMP}, 214 | description = #{record.description,jdbcType=LONGVARCHAR} 215 | 216 | 217 | 218 | 219 | 220 | update ums_gallery 221 | set id = #{record.id,jdbcType=INTEGER}, 222 | user_id = #{record.userId,jdbcType=INTEGER}, 223 | name = #{record.name,jdbcType=VARCHAR}, 224 | url = #{record.url,jdbcType=VARCHAR}, 225 | create_time = #{record.createTime,jdbcType=TIMESTAMP} 226 | 227 | 228 | 229 | 230 | 231 | update ums_gallery 232 | 233 | 234 | user_id = #{userId,jdbcType=INTEGER}, 235 | 236 | 237 | name = #{name,jdbcType=VARCHAR}, 238 | 239 | 240 | url = #{url,jdbcType=VARCHAR}, 241 | 242 | 243 | create_time = #{createTime,jdbcType=TIMESTAMP}, 244 | 245 | 246 | description = #{description,jdbcType=LONGVARCHAR}, 247 | 248 | 249 | where id = #{id,jdbcType=INTEGER} 250 | 251 | 252 | update ums_gallery 253 | set user_id = #{userId,jdbcType=INTEGER}, 254 | name = #{name,jdbcType=VARCHAR}, 255 | url = #{url,jdbcType=VARCHAR}, 256 | create_time = #{createTime,jdbcType=TIMESTAMP}, 257 | description = #{description,jdbcType=LONGVARCHAR} 258 | where id = #{id,jdbcType=INTEGER} 259 | 260 | 261 | update ums_gallery 262 | set user_id = #{userId,jdbcType=INTEGER}, 263 | name = #{name,jdbcType=VARCHAR}, 264 | url = #{url,jdbcType=VARCHAR}, 265 | create_time = #{createTime,jdbcType=TIMESTAMP} 266 | where id = #{id,jdbcType=INTEGER} 267 | 268 | -------------------------------------------------------------------------------- /Code/src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | and ${criterion.condition} 23 | 24 | 25 | and ${criterion.condition} #{criterion.value} 26 | 27 | 28 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 29 | 30 | 31 | and ${criterion.condition} 32 | 33 | #{listItem} 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | and ${criterion.condition} 52 | 53 | 54 | and ${criterion.condition} #{criterion.value} 55 | 56 | 57 | and ${criterion.condition} #{criterion.value} and #{criterion.secondValue} 58 | 59 | 60 | and ${criterion.condition} 61 | 62 | #{listItem} 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | id, loginName, nickName, password, mobilePhone, headerUrl, loginTime, createTime 74 | 75 | 89 | 95 | 96 | delete from user 97 | where id = #{id,jdbcType=INTEGER} 98 | 99 | 100 | delete from user 101 | 102 | 103 | 104 | 105 | 106 | 107 | SELECT LAST_INSERT_ID() 108 | 109 | insert into user (loginName, nickName, password, 110 | mobilePhone, headerUrl, loginTime, 111 | createTime) 112 | values (#{loginname,jdbcType=VARCHAR}, #{nickname,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, 113 | #{mobilephone,jdbcType=VARCHAR}, #{headerurl,jdbcType=VARCHAR}, #{logintime,jdbcType=TIMESTAMP}, 114 | #{createtime,jdbcType=TIMESTAMP}) 115 | 116 | 117 | 118 | SELECT LAST_INSERT_ID() 119 | 120 | insert into user 121 | 122 | 123 | loginName, 124 | 125 | 126 | nickName, 127 | 128 | 129 | password, 130 | 131 | 132 | mobilePhone, 133 | 134 | 135 | headerUrl, 136 | 137 | 138 | loginTime, 139 | 140 | 141 | createTime, 142 | 143 | 144 | 145 | 146 | #{loginname,jdbcType=VARCHAR}, 147 | 148 | 149 | #{nickname,jdbcType=VARCHAR}, 150 | 151 | 152 | #{password,jdbcType=VARCHAR}, 153 | 154 | 155 | #{mobilephone,jdbcType=VARCHAR}, 156 | 157 | 158 | #{headerurl,jdbcType=VARCHAR}, 159 | 160 | 161 | #{logintime,jdbcType=TIMESTAMP}, 162 | 163 | 164 | #{createtime,jdbcType=TIMESTAMP}, 165 | 166 | 167 | 168 | 174 | 175 | update user 176 | 177 | 178 | id = #{record.id,jdbcType=INTEGER}, 179 | 180 | 181 | loginName = #{record.loginname,jdbcType=VARCHAR}, 182 | 183 | 184 | nickName = #{record.nickname,jdbcType=VARCHAR}, 185 | 186 | 187 | password = #{record.password,jdbcType=VARCHAR}, 188 | 189 | 190 | mobilePhone = #{record.mobilephone,jdbcType=VARCHAR}, 191 | 192 | 193 | headerUrl = #{record.headerurl,jdbcType=VARCHAR}, 194 | 195 | 196 | loginTime = #{record.logintime,jdbcType=TIMESTAMP}, 197 | 198 | 199 | createTime = #{record.createtime,jdbcType=TIMESTAMP}, 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | update user 208 | set id = #{record.id,jdbcType=INTEGER}, 209 | loginName = #{record.loginname,jdbcType=VARCHAR}, 210 | nickName = #{record.nickname,jdbcType=VARCHAR}, 211 | password = #{record.password,jdbcType=VARCHAR}, 212 | mobilePhone = #{record.mobilephone,jdbcType=VARCHAR}, 213 | headerUrl = #{record.headerurl,jdbcType=VARCHAR}, 214 | loginTime = #{record.logintime,jdbcType=TIMESTAMP}, 215 | createTime = #{record.createtime,jdbcType=TIMESTAMP} 216 | 217 | 218 | 219 | 220 | 221 | update user 222 | 223 | 224 | loginName = #{loginname,jdbcType=VARCHAR}, 225 | 226 | 227 | nickName = #{nickname,jdbcType=VARCHAR}, 228 | 229 | 230 | password = #{password,jdbcType=VARCHAR}, 231 | 232 | 233 | mobilePhone = #{mobilephone,jdbcType=VARCHAR}, 234 | 235 | 236 | headerUrl = #{headerurl,jdbcType=VARCHAR}, 237 | 238 | 239 | loginTime = #{logintime,jdbcType=TIMESTAMP}, 240 | 241 | 242 | createTime = #{createtime,jdbcType=TIMESTAMP}, 243 | 244 | 245 | where id = #{id,jdbcType=INTEGER} 246 | 247 | 248 | update user 249 | set loginName = #{loginname,jdbcType=VARCHAR}, 250 | nickName = #{nickname,jdbcType=VARCHAR}, 251 | password = #{password,jdbcType=VARCHAR}, 252 | mobilePhone = #{mobilephone,jdbcType=VARCHAR}, 253 | headerUrl = #{headerurl,jdbcType=VARCHAR}, 254 | loginTime = #{logintime,jdbcType=TIMESTAMP}, 255 | createTime = #{createtime,jdbcType=TIMESTAMP} 256 | where id = #{id,jdbcType=INTEGER} 257 | 258 | -------------------------------------------------------------------------------- /Code/src/main/resources/mybatis-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SpringFlutter 2 | 前情提要 3 | ------- 4 | 拿破仑曾经说过:“不想当全栈的工程师不是好程序猿”,因此作为普通程序猿的我们,为了能成为一名好的程序猿,要始终坚持学习的步伐。作为我个人来讲,尽管水平一般,但在安卓开发的道路上尝试了原生、phoneGap、RN等各类框架开发,技能深度不敢说,技能点还算丰富,一套技能下来至少撸掉敌人半管子血。这不,为了干掉敌人另外半管子血,踏上了java web开发的学习之路。曾经,曾经啊,我是想成为一名java后台开发的,学着学着ssh,居然阴差阳错踏入了安卓开发道路(这句话不好理解,我也无法解释。。。)。不扯淡了,言归正传,学习之路必然要伴随撸代码的过程,因此就有了这么一个项目,打算做一个前后端分离的电商项目,后台采用Spring boot,也就是本项目。[前端App](https://github.com/shenmengzhuifeng/SpringFlutterApp)使用目前谷歌的亲儿子Flutter开发,也算是在安卓开发的方向上再添一技能。 5 | 6 | 项目介绍 7 | -------- 8 | 本项目采用Gradle构建方式,通过token及refreshToken实现鉴权及登录状态维护。后台技能栈包括:Spring boot、MyBatis、Spring Security、redis、Druid、MySql、Kafka等。目前通过Spring Security及JJWT实现了账号的登录认证功能,详见第一章。 9 | 10 | 项目目录结构 11 | ----------- 12 | 此处会有截图 13 | 14 | 目录 15 | --- 16 | 第一章 账号登录认证
17 | 第二章 MyBatis Generator代码生成器 18 | 19 | 20 | 账号登录认证 21 | ----------- 22 | 任何应用的开发都离不开用户鉴权,用户的权限维护以及api接口的保护是一个系统开发的必备,也是系统的门户。我们就先从账号登录认证开始,一步步构建本系统。目前常用的鉴权方式有基于session和基于token的方式。由于session的验证方式需要session的服务器存储与维护,存在性能缺陷,也不便于集群部署。因此我们直接采用token的认证机制。这里我就在想怎么才能不着痕迹的过渡到jwt及Spring Security的认证方式使用呢,想来想去,实在是没那个文采。。。就直接开始JWT 的token认证方式吧,至于为啥用,网上一搜一大把,JWT使用起来轻便,开销小,服务端不用记录用户状态信息(无状态),解决单点登录问题,使用签名保证信息传输的安全等等。我们这里还是简单的介绍一下JWT
23 | 24 | JSON Web Token(JWT) 25 | ------------------- 26 | 先附上官方解释:JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,可以在各方之间作为JSON对象安全地传输信息。此信息可以通过数字签名进行验证和信任。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。 27 | 虽然JWT可以加密以在各方之间提供保密,但只将专注于签名令牌。签名令牌可以验证其中包含的声明的完整性,而加密令牌则隐藏其他方的声明。当使用公钥/私钥对签署令牌时,签名还证明只有持有私钥的一方是签署私钥的一方。 28 | 29 | 简单来讲就是JWT可以携带一些用户信息,并且可以进行加密传输。既能反解出用户信息进行识别,又能保证信息的安全可靠。
30 | 31 | JWT工作流程 32 | --------- 33 | 1、用户通过手机app登录注册界面输入用户名、密码或手机号、验证码进行登录(调用后台登录注册接口)
34 | 2、服务器验证登录鉴权,如果用户信息合法,根据用户的信息和服务器的规则生成JWT token及JWT refreshToken
35 | 3、服务器将token、refreshToken(包括各自的有效期等)以json形式返回。
36 | 4、用户得到token及refreshToken等信息,保存于本地及缓存(如SharedPreferences等)
37 | 5、以后用户请求protected中的API时,在请求的header中加入 Authorization: Bearer xxxx(token)。此处注意token之前有一个7字符长度的 Bearer,当然也可以不用加
38 | 6、当token快过期时,通过refreshToken调用服务端接口刷新token,生成新的有效期token,以续期用户登录状态
39 | 7、服务器端受保护接口对token进行检验,如果合法就解析其中内容,根据其拥有的权限和自己的业务逻辑给出对应的响应结果。
40 | 41 | 流程图如下: 42 | 43 | 44 | 45 | JWT总共由三部分组成,每部分之间通过圆点(.)连接,这三部分分别是Header、Payload、Signature。先来看一个例子:
46 | ```java 47 | eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ3ZWkiLCJjcmVhdGVkIjoxNTcyOTYxNzA3NTk4LCJleHAiOjE1NzQ3NzYxMDd9.Ifpyzix1y4GoNWyQ54zyZa18HHutO-sAF-fhPC-jZjKoLd-Nr0WcGqMTuk6BNR062Fj6lihXNszCdGpk82rktw 48 | ``` 49 | 这个例子总共三部分,分别是:
50 | eyJhbGciOiJIUzUxMiJ9
51 | eyJzdWIiOiJ3ZWkiLCJjcmVhdGVkIjoxNTcyOTYxNzA3NTk4LCJleHAiOjE1NzQ3NzYxMDd9
52 | Ifpyzix1y4GoNWyQ54zyZa18HHutO-sAF-fhPC-jZjKoLd-Nr0WcGqMTuk6BNR062Fj6lihXNszCdGpk82rktw
53 | 三部分每一部分都分别是通过[BASE64](https://en.wikipedia.org/wiki/Base64)编码而成。我们通过Base64解码器(可直接百度在线解析)进行解析分别得到以下三部分:
54 | ```java 55 | {"alg":"HS512"} 56 | ``` 57 | ```java 58 | {"sub":"wei","created":1572961707598,"exp":1574776107} 59 | ``` 60 | ```java 61 | !úrÎ,uˁ¨5lçŒòe­|{­:À~˜Ê ·M¯Eœ£ºN5:ØXú–(W6ÌÂtjdójä· 62 | ``` 63 | 第一部分告诉我们HMAC采用HS512算法对JWT进行的签名。第二部分可以看出是我们自己需要传递的信息内容。前两部分可以看出全部都是明文,所以不能放置敏感和隐私信息。第三部分是整个jwt的保障,没有秘钥无法解析其内容。三部分内容的具体实现在后面代码部分说明。 64 | 65 | JWT的生成和解析 66 | ------------- 67 | 这里我们引入[JJWT](https://github.com/jwtk/jjwt)这个开源库,用于JWT的生成。JWT的生成可以使用下面这样的代码完成:
68 | ```java 69 | 70 | /** 71 | * 根据用户信息生成token 72 | */ 73 | public String generateToken(UserDetails userDetails) { 74 | Map claims = new HashMap<>(); 75 | claims.put(Claims.SUBJECT, userDetails.getUsername()); 76 | claims.put(CLAIM_KEY_CREATED, new Date()); 77 | return generateToken(claims); 78 | } 79 | 80 | /** 81 | * 根据负责生成JWT的token 82 | */ 83 | private String generateToken(Map claims) { 84 | return Jwts.builder() 85 | .setClaims(claims) 86 | .setExpiration(generateExpirationDate()) 87 | .signWith(SignatureAlgorithm.HS512, secret) 88 | .compact(); 89 | } 90 | 91 | /** 92 | * 根据负责生成JWT的refreshToken 93 | */ 94 | private String generateRefreshToken(Map claims) { 95 | return Jwts.builder() 96 | .setClaims(claims) 97 | .setExpiration(generateRefreshTokenExpirationDate()) 98 | .signWith(SignatureAlgorithm.HS512, secret) 99 | .compact(); 100 | } 101 | ``` 102 | 这里方法中的claims参数就是我们要携带在jwt中第二部分的信息,setExpiration设置token过期时间。这里其实两种方式设置都可以,通过把过期时间放到claims里面也可以。我们通过JJWT源码可以很容易理解,Claims类中声明了如下静态变量可供直接使用, 103 | ```java 104 | /** JWT {@code Issuer} claims parameter name: "iss" */ 105 | public static final String ISSUER = "iss"; 106 | 107 | /** JWT {@code Subject} claims parameter name: "sub" */ 108 | public static final String SUBJECT = "sub"; 109 | 110 | /** JWT {@code Audience} claims parameter name: "aud" */ 111 | public static final String AUDIENCE = "aud"; 112 | 113 | /** JWT {@code Expiration} claims parameter name: "exp" */ 114 | public static final String EXPIRATION = "exp"; 115 | 116 | /** JWT {@code Not Before} claims parameter name: "nbf" */ 117 | public static final String NOT_BEFORE = "nbf"; 118 | 119 | /** JWT {@code Issued At} claims parameter name: "iat" */ 120 | public static final String ISSUED_AT = "iat"; 121 | 122 | /** JWT {@code JWT ID} claims parameter name: "jti" */ 123 | public static final String ID = "jti"; 124 | ``` 125 | 这些属性既能通过对应方法设置也可以直接通过map设置到claims中。其中signWith方法传入我们自己的秘钥。
126 | 解析也很简单,利用 jjwt 提供的parser传入秘钥,然后就可以解析token了。 127 | 128 | ```java 129 | /** 130 | * 从token中获取JWT中的负载 131 | */ 132 | private Claims getClaimsFromToken(String token) { 133 | Claims claims = null; 134 | try { 135 | claims = Jwts.parser() 136 | .setSigningKey(secret) 137 | .parseClaimsJws(token) 138 | .getBody(); 139 | } catch (Exception e) { 140 | LOGGER.info("JWT格式验证失败:{}",token); 141 | } 142 | return claims; 143 | } 144 | ``` 145 | 146 | JWT本身的生成与解析比较简单,重点在于集成到Spring boot中,串联整个权限校验。这里我们通过Spring的一个子项目Spring Security与JJWT结合使用完成本系统的鉴权工作。
147 | 148 | Spring Security 149 | --------------- 150 | [Spring Security](http://projects.spring.io/spring-security/)是一个基于Spring的通用安全框架,采用了责任链设计模式,它有一条很长的过滤器链。做过Android开发的应该都用过网络请求框架OKHttp,这里的过滤器链就类似OKHttp的各个网络拦截器。拦截器相关的所有配置均位于WebSecurityConfigurerAdapter类中,可实现如下:
151 | ```java 152 | @Configuration 153 | @EnableWebSecurity 154 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 155 | // Spring会自动寻找同样类型的具体类注入,这里就是JwtUserDetailsServiceImpl了 156 | @Autowired 157 | private UserDetailsService userDetailsService; 158 | @Autowired 159 | private RestfulAccessDeniedHandler restfulAccessDeniedHandler; 160 | @Autowired 161 | private RestAuthenticationEntryPoint restAuthenticationEntryPoint; 162 | 163 | @Autowired 164 | public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { 165 | authenticationManagerBuilder 166 | // 设置UserDetailsService 167 | .userDetailsService(this.userDetailsService) 168 | // 使用BCrypt进行密码的hash 169 | .passwordEncoder(passwordEncoder()); 170 | } 171 | // 装载BCrypt密码编码器 172 | @Bean 173 | public PasswordEncoder passwordEncoder() { 174 | return new BCryptPasswordEncoder(); 175 | } 176 | 177 | @Bean 178 | public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){ 179 | return new JwtAuthenticationTokenFilter(); 180 | } 181 | 182 | @Override 183 | protected void configure(HttpSecurity httpSecurity) throws Exception { 184 | httpSecurity 185 | // 由于使用的是JWT,我们这里不需要csrf 186 | .csrf().disable() 187 | 188 | // 基于token,所以不需要session 189 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 190 | 191 | .authorizeRequests() 192 | //.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() 193 | 194 | // 允许对于网站静态资源的无授权访问 195 | .antMatchers( 196 | HttpMethod.GET, 197 | "/", 198 | "/*.html", 199 | "/favicon.ico", 200 | "/**/*.html", 201 | "/**/*.css", 202 | "/**/*.js" 203 | ).permitAll() 204 | // 对于获取token的rest api要允许匿名访问 205 | .antMatchers("/auth/**").permitAll() 206 | // 除上面外的所有请求全部需要鉴权认证 207 | .anyRequest().authenticated(); 208 | 209 | // 禁用缓存 210 | httpSecurity.headers().cacheControl(); 211 | // 添加JWT filter 212 | httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); 213 | //添加自定义未授权和未登录结果返回 214 | httpSecurity.exceptionHandling() 215 | .accessDeniedHandler(restfulAccessDeniedHandler) 216 | .authenticationEntryPoint(restAuthenticationEntryPoint); 217 | } 218 | } 219 | ``` 220 | 配置简介 221 | ------ 222 | configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) 223 | 224 | AuthenticationManager 的建造器,配置 AuthenticationManagerBuilder 会让Security 自动构建一个 AuthenticationManager;如果想要使用该功能你需要配置一个 UserDetailService 和 PasswordEncoder。UserDetailsService 用于在认证器中根据用户传过来的用户名查找一个用户, PasswordEncoder 用于密码的加密与比对,我们存储用户密码的时候用PasswordEncoder.encode() 加密存储,在认证器里会调用 PasswordEncoder.matches() 方法进行密码比对。如果重写了该方法,Security 会启用 DaoAuthenticationProvider 这个认证器,该认证就是先调用 UserDetailsService.loadUserByUsername 然后使用 PasswordEncoder.matches() 进行密码比对,如果认证成功成功则返回一个 Authentication 对象。 225 | 226 | configure(HttpSecurity httpSecurity) 227 | 228 | 这个配置方法是整个Spring Security的关键,也是最复杂。本项目中用到的已在上面代码中进行注释,这里唯一要说明的是addFilterBefore方法,指插入对应的过滤器之前,还有addFilterAfter 加在对应的过滤器之后,addFilterAt 加在过滤器同一位置。 229 | 230 | 代码具体实现 231 | ---------- 232 | 功能采用MySql数据库,先创建数据库springflutter,并在数据库springflutter中创建user表。表结构如下:
233 | 234 | ![](https://github.com/shenmengzhuifeng/SpringFlutter/blob/master/images/user_table.jpg) 235 | 236 | 为了方便用户名密码认证,在user表中直接插入了一条数据,后面实现了注册接口之后可先通过注册接口生成用户信息再调用登录接口登录。为了方便,插入数据的密码暂时以明文方式展现,后面将统一密码加密处理。
237 | 1、首先创建Spring boot项目SpringFlutter,采用Gradle编译方式,其中最简单的一种是通过一个叫Spring Initializr的在线工具 http://start.spring.io/ 进行工程的生成。也可以通过Intellij IED直接创建。创建成功之后在IDE中打开,并创建module,命名为Code。当然这里你也可以不创建submodule,为了后期代码的目录维护,我这里创建了module目录Code。修改settings.gradle文件如下:
238 | ```java 239 | include 'Code' 240 | ``` 241 | 在code目录下的build.gradle下加入如下依赖
242 | ```java 243 | dependencies { 244 | testCompile group: 'junit', name: 'junit', version: '4.12' 245 | compile('org.springframework.boot:spring-boot-starter-web') //起步依赖 246 | compile('org.springframework.boot:spring-boot-starter-jdbc')//起步依赖 247 | compile('com.alibaba:druid-spring-boot-starter:1.1.10')//druid数据源 248 | compile("org.springframework.boot:spring-boot-starter-security")//Spring Security起步依赖 249 | compile("org.springframework.security.oauth:spring-security-oauth2")//Spring Security oauth2 250 | compile("org.springframework.security:spring-security-jwt") 251 | compile("mysql:mysql-connector-java") 252 | compile('io.jsonwebtoken:jjwt:0.9.0')//jjwt库 253 | compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1')//mybatis起步依赖 254 | compile('mysql:mysql-connector-java:8.0.11') 255 | compile('cn.hutool:hutool-all:4.5.7')//方法工具库 256 | } 257 | ``` 258 | 在application.yml(可在resource文件夹下新建此文件,application.properties文件就不用了,区别可自行百度)文件添加如下内容:
259 | ```java 260 | spring: 261 | profiles: 262 | active: dev #默认为开发环境 263 | datasource: 264 | #mysql数据库 265 | url: jdbc:mysql://localhost:3306/springflutter 266 | #数据库用户名 267 | username: root 268 | #密码 269 | password: 123456 270 | type: com.alibaba.druid.pool.DruidDataSource 271 | druid: 272 | initial-size: 5 #连接池初始化大小 273 | min-idle: 10 #最小空闲连接数 274 | max-active: 20 #最大连接数 275 | web-stat-filter: 276 | exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" #不统计这些请求数据 277 | stat-view-servlet: #访问监控网页的登录用户名和密码 278 | login-username: druid 279 | login-password: druid 280 | server: 281 | port: 8089 #服务运行端口 282 | 283 | mybatis: 284 | mapper-locations: 285 | - classpath:mapper/*.xml #mybatis 对应的mapper路径 286 | 287 | jwt: 288 | tokenHeader: Authorization #JWT存储的请求头 289 | secret: mySecret #JWT加解密使用的密钥 290 | expiration: 1814400 #JWT的超期限时间(60*60*24*3) 291 | expirationRefreshToken: 54432000 #JWT的超期限时间(60*60*24*90) 292 | tokenHead: Bearer #JWT负载中拿到开头 293 | 294 | logging: 295 | level: 296 | root: info #日志配置DEBUG,INFO,WARN,ERROR 297 | # file: demo_log.log #配置日志生成路径 298 | # path: /var/logs #配置日志文件名称 299 | 300 | ``` 301 | 一切配置就绪(数据库用户名密码修改为自己的),准备写代码了,首先创建用户表的映射类User
302 | ```java 303 | public class User { 304 | 305 | private String loginName; 306 | 307 | private String nickName; 308 | 309 | private String customerId; 310 | 311 | private String headerUrl; 312 | 313 | private String mobilePhone; 314 | 315 | private String password; 316 | ``` 317 | 省略set、get方法,然后创建用户表操作对应的Mapper类与xml文件,UserMapper、UserMapper.xml
318 | ```java 319 | @Mapper 320 | public interface UserMapper { 321 | User selectUserByLoginName(@Param("loginName") String loginName); 322 | } 323 | ``` 324 | ```java 325 | 326 | 327 | 328 | 329 | 332 | 333 | ``` 334 | 创建Spring Security中的UserDetailsService实现类
335 | ```java 336 | @Service 337 | public class UserDetailServiceImpl implements UserDetailsService { 338 | 339 | @Autowired 340 | private UserMapper mUserMapper; 341 | 342 | @Override 343 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 344 | User user = mUserMapper.selectUserByLoginName(username); 345 | if (user != null) { 346 | return new JwtUserDetail(user); 347 | } 348 | throw new UsernameNotFoundException("用户名或密码错误"); 349 | } 350 | } 351 | ``` 352 | 创建Spring Security中UserDetails的实现类
353 | ```java 354 | public class JwtUserDetail implements UserDetails { 355 | 356 | private User mUser; 357 | 358 | 359 | public JwtUserDetail(User user){ 360 | this.mUser = user; 361 | } 362 | 363 | @Override 364 | public Collection getAuthorities() { 365 | return null; 366 | } 367 | 368 | @Override 369 | public String getPassword() { 370 | return mUser.getPassword(); 371 | } 372 | 373 | @Override 374 | public String getUsername() { 375 | return mUser.getLoginName(); 376 | } 377 | 378 | @Override 379 | public boolean isAccountNonExpired() { 380 | return false;//暂未实现 381 | } 382 | 383 | @Override 384 | public boolean isAccountNonLocked() { 385 | return false;//暂未实现 386 | } 387 | 388 | @Override 389 | public boolean isCredentialsNonExpired() { 390 | return false;//暂未实现 391 | } 392 | 393 | @Override 394 | public boolean isEnabled() { 395 | return false;//暂未实现 396 | } 397 | ``` 398 | 创建UserService,作为用户相关操作类,与UserDetailService不同,这个实现类会包括所有用户相关操作
399 | ```java 400 | @Service 401 | public class UserServiceImpl implements UserService { 402 | 403 | @Autowired 404 | private UserDetailsService mUserDetailsService; 405 | 406 | @Autowired 407 | private PasswordEncoder mPasswordEncoder; 408 | 409 | @Autowired 410 | private JwtTokenUtil mJwtTokenUtil; 411 | 412 | @Value("${jwt.expiration}") 413 | private Long mExpiration; 414 | @Value("${jwt.expirationRefreshToken}") 415 | private Long mExpirationRefreshToken; 416 | 417 | @Override 418 | public String register() { 419 | return null; 420 | } 421 | 422 | @Override 423 | public CustomerInfoReply login(String username, String password) { 424 | UserDetails userDetails = mUserDetailsService.loadUserByUsername(username); 425 | // if(!mPasswordEncoder.matches(password,userDetails.getPassword())){ 426 | // throw new BadCredentialsException("密码不正确"); 427 | // } //这里暂时不对密码进行加密校验 428 | if(!password.equals(userDetails.getPassword())){ 429 | throw new BadCredentialsException("密码不正确"); 430 | } 431 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 432 | SecurityContextHolder.getContext().setAuthentication(authentication); 433 | String token = mJwtTokenUtil.generateToken(userDetails); 434 | String refreshToken = mJwtTokenUtil.generateRefreshToken(userDetails); 435 | return new CustomerInfoReply(token,refreshToken,mExpiration,mExpirationRefreshToken); 436 | } 437 | ``` 438 | 这里的login方法通过从数据库里面查到的用户名生成jwt token refreshToken,JwtTokenUtil类的具体实现如下。
439 | 440 | ```java 441 | /** 442 | * JwtToken生成的工具类 443 | * JWT token的格式:header.payload.signature 444 | * header的格式(算法、token的类型): 445 | * {"alg": "HS512","typ": "JWT"} 446 | * payload的格式(用户名、创建时间、生成时间): 447 | * {"sub":"wang","created":1489079981393,"exp":1489684781} 448 | * signature的生成算法: 449 | * HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret) 450 | * Created by wei 451 | */ 452 | @Component 453 | public class JwtTokenUtil { 454 | private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class); 455 | private static final String CLAIM_KEY_CREATED = "created"; 456 | @Value("${jwt.secret}") 457 | private String secret; 458 | @Value("${jwt.expiration}") 459 | private Long expiration; 460 | @Value("${jwt.expirationRefreshToken}") 461 | private Long expirationRefreshToken; 462 | 463 | /** 464 | * 根据负责生成JWT的token 465 | */ 466 | private String generateToken(Map claims) { 467 | return Jwts.builder() 468 | .setClaims(claims) 469 | .setExpiration(generateExpirationDate()) 470 | .signWith(SignatureAlgorithm.HS512, secret) 471 | .compact(); 472 | } 473 | 474 | /** 475 | * 根据负责生成JWT的refreshToken 476 | */ 477 | private String generateRefreshToken(Map claims) { 478 | return Jwts.builder() 479 | .setClaims(claims) 480 | .setExpiration(generateRefreshTokenExpirationDate()) 481 | .signWith(SignatureAlgorithm.HS512, secret) 482 | .compact(); 483 | } 484 | 485 | /** 486 | * 从token中获取JWT中的负载 487 | */ 488 | private Claims getClaimsFromToken(String token) { 489 | Claims claims = null; 490 | try { 491 | claims = Jwts.parser() 492 | .setSigningKey(secret) 493 | .parseClaimsJws(token) 494 | .getBody(); 495 | } catch (Exception e) { 496 | LOGGER.info("JWT格式验证失败:{}",token); 497 | } 498 | return claims; 499 | } 500 | 501 | /** 502 | * 生成token的过期时间 503 | */ 504 | private Date generateExpirationDate() { 505 | return new Date(System.currentTimeMillis() + expiration * 1000); 506 | } 507 | /** 508 | * 生成refreshToken的过期时间 509 | */ 510 | private Date generateRefreshTokenExpirationDate() { 511 | return new Date(System.currentTimeMillis() + expirationRefreshToken * 1000); 512 | } 513 | 514 | /** 515 | * 从token中获取登录用户名 516 | */ 517 | public String getUserNameFromToken(String token) { 518 | String username; 519 | try { 520 | Claims claims = getClaimsFromToken(token); 521 | username = claims.getSubject(); 522 | } catch (Exception e) { 523 | username = null; 524 | } 525 | return username; 526 | } 527 | 528 | /** 529 | * 验证token是否还有效 530 | * 531 | * @param token 客户端传入的token 532 | * @param userDetails 从数据库中查询出来的用户信息 533 | */ 534 | public boolean validateToken(String token, UserDetails userDetails) { 535 | String username = getUserNameFromToken(token); 536 | return username.equals(userDetails.getUsername()) && !isTokenExpired(token); 537 | } 538 | 539 | /** 540 | * 判断token是否已经失效 541 | */ 542 | private boolean isTokenExpired(String token) { 543 | Date expiredDate = getExpiredDateFromToken(token); 544 | return expiredDate.before(new Date()); 545 | } 546 | 547 | /** 548 | * 从token中获取过期时间 549 | */ 550 | private Date getExpiredDateFromToken(String token) { 551 | Claims claims = getClaimsFromToken(token); 552 | return claims.getExpiration(); 553 | } 554 | 555 | /** 556 | * 根据用户信息生成token 557 | */ 558 | public String generateToken(UserDetails userDetails) { 559 | Map claims = new HashMap<>(); 560 | claims.put(Claims.SUBJECT, userDetails.getUsername()); 561 | claims.put(CLAIM_KEY_CREATED, new Date()); 562 | return generateToken(claims); 563 | } 564 | /** 565 | * 根据用户信息生成token 566 | */ 567 | public String generateRefreshToken(UserDetails userDetails) { 568 | Map claims = new HashMap<>(); 569 | claims.put(Claims.SUBJECT, userDetails.getUsername()); 570 | claims.put(CLAIM_KEY_CREATED, new Date()); 571 | return generateRefreshToken(claims); 572 | } 573 | 574 | /** 575 | * 判断token是否可以被刷新 576 | */ 577 | public boolean canRefresh(String token) { 578 | return !isTokenExpired(token); 579 | } 580 | 581 | /** 582 | * 刷新token 583 | */ 584 | public String refreshToken(String token) { 585 | Claims claims = getClaimsFromToken(token); 586 | claims.put(CLAIM_KEY_CREATED, new Date()); 587 | return generateToken(claims); 588 | } 589 | } 590 | ``` 591 | 接下来创建UserController类,添加登录接口映射方法login:
592 | ```java 593 | @RestController 594 | public class UserController { 595 | private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class); 596 | 597 | @Autowired 598 | private UserService mUserService; 599 | 600 | @Autowired 601 | private UserMapper userMapper; 602 | 603 | @Autowired 604 | private JwtTokenUtil jwtTokenUtil; 605 | 606 | @Value("${jwt.tokenHeader}") 607 | private String tokenHeader; 608 | @Value("${jwt.tokenHead}") 609 | private String tokenHead; 610 | 611 | @RequestMapping(value = UnifyApiUri.UserApi.API_CUSTOMER_INFO,method = RequestMethod.GET) 612 | public CommonResp getCustomerInfo(HttpServletRequest request) { 613 | String authHeader = request.getHeader(this.tokenHeader); 614 | if (authHeader != null && authHeader.startsWith(this.tokenHead)) { 615 | String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer " 616 | String username = jwtTokenUtil.getUserNameFromToken(authToken); 617 | User user = userMapper.selectUserByLoginName(username); 618 | return CommonResp.success(user); 619 | }else { 620 | return new CommonResp(Constants.RESULT_ERROR,ResultCode.RESULT_CODE_1002.getCode() 621 | ,ResultCode.RESULT_CODE_1002.getMessage(),null); 622 | } 623 | } 624 | 625 | @RequestMapping(value = UnifyApiUri.UserApi.API_AUTH_LOGIN, 626 | method = RequestMethod.POST,produces= MediaType.APPLICATION_JSON_UTF8_VALUE) 627 | public CommonResp login(@RequestBody AuthenticationRequest authenticationRequest) { 628 | LOGGER.info("login info==>" + authenticationRequest.toString()); 629 | CustomerInfoReply customerInfoReply = mUserService.login(authenticationRequest.getUsername(),authenticationRequest.getPassword()); 630 | LOGGER.info("customerInfoReply info==>" + customerInfoReply.toString()); 631 | return CommonResp.success(customerInfoReply); 632 | } 633 | } 634 | ``` 635 | 636 | login方法解析
637 | ----------- 638 | 方法请求方式为post,请求参数设置类型为RequestBody,安卓端采用okhttp的postString方法进行请求。首先从请求参数中获取用户名密码,其中请求body体类如下: 639 | 640 | ```java 641 | public class AuthenticationRequest extends CommonRequest{ 642 | @NotEmpty(message = "用户名不能为空") 643 | private String username; 644 | @NotEmpty(message = "密码不能为空") 645 | private String password; 646 | 647 | public String getUsername() { 648 | return username; 649 | } 650 | 651 | public void setUsername(String username) { 652 | this.username = username; 653 | } 654 | 655 | public String getPassword() { 656 | return password; 657 | } 658 | 659 | public void setPassword(String password) { 660 | this.password = password; 661 | } 662 | 663 | @Override 664 | public String toString() { 665 | return "AuthenticationRequest{" + 666 | "username='" + username + '\'' + 667 | ", password='" + password + '\'' + 668 | '}'; 669 | } 670 | } 671 | ``` 672 | 获取到请求的用户名和密码之后调用UserService类的login方法进行登录,登录成功返回CustomerInfoReply
673 | ```java 674 | public class CustomerInfoReply { 675 | 676 | private String token; 677 | 678 | private String refreshToken; 679 | 680 | private Long tokenExpireTime; 681 | 682 | private Long refreshTokenExpireTime; 683 | ``` 684 | 整个登录并返回token的具体过程已经结束,拿到返回的token,终端请求相关接口时带上token。
685 | ![](https://github.com/shenmengzhuifeng/SpringFlutter/blob/master/images/image_login.png) 686 | 687 | 我们发现UserController类中出来login方法还有一个getCustomerInfo方法用于获取用户详细信息,此方法需要校验token,并通过token里面的loginName查询相关用户信息。Spring Security会在请求到达Controller之前先对token的格式、有效期等做校验。这里我们就需要添加token校验的过滤器,用于校验token,过滤器类实现如下:
688 | ```java 689 | public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { 690 | private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class); 691 | @Autowired 692 | private UserDetailsService userDetailsService; 693 | @Autowired 694 | private JwtTokenUtil jwtTokenUtil; 695 | @Value("${jwt.tokenHeader}") 696 | private String tokenHeader; 697 | @Value("${jwt.tokenHead}") 698 | private String tokenHead; 699 | 700 | @Override 701 | protected void doFilterInternal(HttpServletRequest request, 702 | HttpServletResponse response, 703 | FilterChain chain) throws ServletException, IOException { 704 | String authHeader = request.getHeader(this.tokenHeader); 705 | if (authHeader != null && authHeader.startsWith(this.tokenHead)) { 706 | String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer " 707 | String username = jwtTokenUtil.getUserNameFromToken(authToken); 708 | LOGGER.info("checking username:{}", username); 709 | if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { 710 | UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); 711 | if (jwtTokenUtil.validateToken(authToken, userDetails)) { 712 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); 713 | authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 714 | LOGGER.info("authenticated user:{}", username); 715 | SecurityContextHolder.getContext().setAuthentication(authentication); 716 | } 717 | } 718 | } 719 | chain.doFilter(request, response); 720 | } 721 | } 722 | ``` 723 | 创建JwtAuthenticationTokenFilter之后,为了使其生效,需要将其加入到Spring Security过滤器链中,实现如下:
724 | ```java 725 | // 添加JWT filter 726 | httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); 727 | ``` 728 | ![](https://github.com/shenmengzhuifeng/SpringFlutter/blob/master/images/image_getCustomerInfo.png) 729 | 730 | 前面对于WebSecurityConfig已经展示,这里不再赘述,这样就实现了token的整个认证流程。 731 | 732 | 第二章 MyBatis Generator代码生成器 733 | ------------------------------- 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '1.5.8.RELEASE' 4 | gradleDockerVersion = '1.2' 5 | gradleDMVersion = '1.0.3.RELEASE' 6 | 7 | } 8 | repositories { 9 | maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} 10 | maven { url 'https://repo.spring.io/libs-milestone' } 11 | mavenCentral() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 16 | classpath("se.transmode.gradle:gradle-docker:${gradleDockerVersion}") 17 | classpath("io.spring.gradle:dependency-management-plugin:${gradleDMVersion}") 18 | } 19 | } 20 | 21 | 22 | allprojects { 23 | repositories() { 24 | maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'} 25 | maven { url 'https://repo.spring.io/libs-milestone' } 26 | mavenCentral() 27 | jcenter() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenmengzhuifeng/SpringFlutter/52baa9da26ef90ee436d11d017ecd829809f2d8b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /images/image_getCustomerInfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenmengzhuifeng/SpringFlutter/52baa9da26ef90ee436d11d017ecd829809f2d8b/images/image_getCustomerInfo.png -------------------------------------------------------------------------------- /images/image_login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenmengzhuifeng/SpringFlutter/52baa9da26ef90ee436d11d017ecd829809f2d8b/images/image_login.png -------------------------------------------------------------------------------- /images/user_table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shenmengzhuifeng/SpringFlutter/52baa9da26ef90ee436d11d017ecd829809f2d8b/images/user_table.jpg -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'Code' 2 | include 'Code-common' 3 | 4 | --------------------------------------------------------------------------------