Real project summary

Posted by tefuzz on Fri, 17 Dec 2021 16:50:32 +0100

1, As an architect, write gateway microservices with other students

package com.kkb.kkbgateway.authorization;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.kkb.kkbcommon.constant.AuthConstant;
import com.kkb.kkbcommon.domain.UserDto;
import com.kkb.kkbgateway.config.IgnoreUrlsConfig;
import com.nimbusds.jose.JWSObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import reactor.core.publisher.Mono;

import java.net.URI;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**

  • The authentication manager is used to determine whether there is access to resources
    */
    @Component
    public class AuthorizationManager implements ReactiveAuthorizationManager {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;

    @Override
    public Mono check(Mono mono, AuthorizationContext authorizationContext) {
    ServerHttpRequest request = authorizationContext.getExchange().getRequest();
    URI uri = request.getURI();
    PathMatcher pathMatcher = new AntPathMatcher();
    //White list path direct release
    List ignoreUrls = ignoreUrlsConfig.getUrls();
    for (String ignoreUrl : ignoreUrls) {
    if (pathMatcher.match(ignoreUrl, uri.getPath())) {
    return Mono.just(new AuthorizationDecision(true));
    }
    }
    //Direct release of cross domain pre inspection requests
    if(request.getMethod() == HttpMethod.OPTIONS){
    return Mono.just(new AuthorizationDecision(true));
    }

     // Different user systems are not allowed to access each other
     try {
         String token = request.getHeaders().getFirst(AuthConstant.JWT_TOKEN_HEADER);
         if(StrUtil.isEmpty(token)){
             return Mono.just(new AuthorizationDecision(false));
         }
         String realToken = token.replace(AuthConstant.JWT_TOKEN_PREFIX, "");
         JWSObject jwsObject = JWSObject.parse(realToken);
         String userStr = jwsObject.getPayload().toString();
         UserDto userDto = JSONUtil.toBean(userStr, UserDto.class);
         if (AuthConstant.ADMIN_CLIENT_ID.equals(userDto.getClientId()) && !pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) {
             return Mono.just(new AuthorizationDecision(false));
         }
         if (AuthConstant.PORTAL_CLIENT_ID.equals(userDto.getClientId()) && pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) {
             return Mono.just(new AuthorizationDecision(false));
         }
     } catch (ParseException e) {
         e.printStackTrace();
         return Mono.just(new AuthorizationDecision(false));
     }
     // Non management end path direct release
     if (!pathMatcher.match(AuthConstant.ADMIN_URL_PATTERN, uri.getPath())) {
         return Mono.just(new AuthorizationDecision(true));
     }
     // The management side path needs to verify permissions
     Map<Object, Object> resourceRolesMap = redisTemplate.opsForHash().entries(AuthConstant.RESOURCE_ROLES_MAP_KEY);
     Iterator<Object> iterator = resourceRolesMap.keySet().iterator();
     List<String> authorities = new ArrayList<>();
     while (iterator.hasNext()) {
         String pattern = (String) iterator.next();
         if (pathMatcher.match(pattern, uri.getPath())) {
             authorities.addAll(Convert.toList(String.class, resourceRolesMap.get(pattern)));
         }
     }
     authorities = authorities.stream().map(i -> i = AuthConstant.AUTHORITY_PREFIX + i).collect(Collectors.toList());
     //Users who have passed the authentication and matched roles can access the current path
     return mono
             .filter(Authentication::isAuthenticated)
             .flatMapIterable(Authentication::getAuthorities)
             .map(GrantedAuthority::getAuthority)
             .any(authorities::contains)
             .map(AuthorizationDecision::new)
             .defaultIfEmpty(new AuthorizationDecision(false));
    

    }
    }
    I learned a lot of gateway related knowledge here and called other micro services through fegin

2, Writing interfaces in Apifox

3, Write code

package com.kkb.kkbportal.controller;

import com.github.pagehelper.PageInfo;
import com.kkb.kkbcommon.api.CommonPage;
import com.kkb.kkbcommon.api.CommonResult;
import com.kkb.kkbportal.domain.ums.User;
import com.kkb.kkbportal.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Api(tags = "user management", description = "user management")
@RequestMapping("/user")
public class UserController {

@Autowired
private UserService userService;

@ApiOperation(value = "Sign in", notes = "Login interface")
@ApiImplicitParam(name = "condition", value = "Information required for user login", dataType = "User")
@PostMapping("/login")
public CommonResult<User> login(@RequestBody @Validated User condition) {
    userService.userLogin(condition);
    return CommonResult.success(null, "Login succeeded");
}

@ApiOperation(value = "register", notes = "Register interface")
@ApiImplicitParam(name = "condition", value = "Information required for user registration", dataType = "User")
@PostMapping("/register")
public CommonResult<User> register(@RequestBody @Validated User user) {
    userService.userRegister(user);
    return CommonResult.success(null, "login was successful");
}

@ApiOperation(value = "Paging query of user information", notes = "User paging query interface")
@ApiImplicitParams({
        @ApiImplicitParam(name = "condition", value = "User filter criteria", dataType = "User"),
        @ApiImplicitParam(name = "pageNum", value = "Current number of pages", defaultValue = "1", dataType = "int"),
        @ApiImplicitParam(name = "pageSize", value = "Pages per page", defaultValue = "10", dataType = "int")
})
@PostMapping("/query/page")
public CommonResult<CommonPage<User>> listPage(@RequestBody User condition,
                                               @RequestParam(defaultValue = "1") Integer pageNum,
                                               @RequestParam(defaultValue = "10") Integer pageSize) {
    PageInfo<User> page = userService.selectPage(condition, pageNum, pageSize);
    System.out.println(page.getList());
    CommonPage<User> commonPage = CommonPage.restPage(page.getList());
    return CommonResult.success(commonPage, "query was successful");
}

@ApiOperation(value = "According to user id Add role", notes = "user-Add interface to role relationship")
@ApiImplicitParams({
        @ApiImplicitParam(name = "userId", value = "user id", dataType = "long"),
        @ApiImplicitParam(name = "roleId", value = "role id", dataType = "long")
})
@PostMapping("/add/role")
public ResponseEntity<String> selectRoleByUserId(@RequestParam("userId") Long userId, @RequestParam("roleId") Long roleId) {
    userService.selectRoleByUserId(userId, roleId);
    return ResponseEntity.ok("User role relationship added successfully");
}

@ApiOperation(value = "According to user id Find user information", notes = "according to id Query user information interface")
@ApiImplicitParams(@ApiImplicitParam(name = "id", value = "user id", dataType = "long"))
@GetMapping("/{id}")
public CommonResult<User> selectUserById(@PathVariable("id") Long id) {
    User user = userService.selectUserById(id);
    return CommonResult.success(user, "query was successful");
}

@ApiOperation(value = "According to user id Modify user", notes = "User modification interface")
@ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "user id", dataType = "long"),
        @ApiImplicitParam(name = "user", value = "user id", dataType = "User")
})
@PutMapping("/update/{id}")
public CommonResult<User> updateUserById(@PathVariable("id") Long id, @RequestBody User user) {
    userService.updateById(id, user);
    return CommonResult.success(null, "Modified successfully");
}

@ApiOperation(value = "According to user id Perform logical deletion", notes = "User delete interface")
@ApiImplicitParam(name = "id", value = "user id", dataType = "long")
@DeleteMapping("/delete/{id}")
public CommonResult<User> deleteUserById(@PathVariable("id") Long id) {
    userService.deleteById(id);
    return CommonResult.success(null, "Delete succeeded");
}

@ApiOperation(value = "User information list query", notes = "User list query interface")
@ApiImplicitParam(name = "condition", value = "User filter criteria", dataType = "User")
@PostMapping("/query/list")
public CommonResult<List<User>> list(@RequestBody User condition) {
    List<User> page = userService.selectByCondition(condition);
    System.out.println(page);
    return CommonResult.success(page, "query was successful");
}

@ApiOperation(value = "Send verification code", notes = "User clicks to obtain verification code interface")
@ApiImplicitParam(name = "phoneNumber", value = "User mobile number", dataType = "String")
@PostMapping("/password")
public ResponseEntity<String> sendSMSCode(@RequestParam("phoneNumber") String phoneNumber) {
    userService.forgetPassword(phoneNumber);
    return ResponseEntity.ok("Sending verification code succeeded");
}

@ApiOperation(value = "Verify the account number according to the verification code", notes = "Verification code login-User clicks OK interface")
@ApiImplicitParams({
        @ApiImplicitParam(name = "phoneNumber", value = "User mobile number", dataType = "String"),
        @ApiImplicitParam(name = "code", value = "Verification Code", dataType = "String")
})
@PostMapping("/password/verification")
public CommonResult<User> sendSMSCode(@RequestParam("phoneNumber") String phoneNumber, @RequestParam("code") String code) {
    User user = userService.smsCodeVerify(phoneNumber, code);
    return CommonResult.success(user, "Verification code login succeeded");
}

}

4, Learned git upload their own branches, and pull branches

Step 1: synchronize the remote warehouse Code: git pull

Step 2: view the current status: git status

Step 3: submit the code to the local git cache: git add

Step 4: push the code to the local git Library: git commit

Step 5: submit the local code to the remote warehouse: git push

5, Project summary

1. Through this project, I think teamwork development ability is very important. Many problems and project details need to be discussed and solved together. It is difficult for a person to think about them very considerate.
2. At the beginning of the project, you must analyze the needs clearly, otherwise you will encounter more problems later
3. Test during writing to prevent more errors
4. Take the initiative to learn what you don't understand by checking materials or videos
5. If you can't write, you must have the cheek to try to write. It's painful at first, but it's better later

6, Reading notes of Java Development Manual

1. The naming in the code cannot start with an underscore or dollar sign, nor can it end with an underscore or dollar sign.
2. It is forbidden to use pinyin and English for all programming related naming, let alone Chinese directly. Note: correct English spelling and grammar can make readers easy to understand and avoid ambiguity. Note that pure Pinyin naming should be avoided. Positive examples: international names such as ali / alibaba / taobao / cainiao/ aliyun/ youku / hangzhou can be regarded as English.
3. All constant names are capitalized, and words are separated by underscores, so as to make the semantic expression complete and clear, and do not be too long.
4. Avoid using identical names between member variables of child parent classes or local variables of different code blocks, so as to reduce readability.
5. If the module, interface, class and method use the design pattern, the specific pattern shall be reflected in the naming.
6. Naming conventions of each layer:
A) Service/DAO layer method naming convention
1) The method to get a single object is prefixed with get.
2) The method to obtain multiple objects is prefixed with list and terminated with a complex number, such as listObjects.
3) The method to obtain the statistical value is prefixed with count.
4) The inserted method is prefixed with save/insert.
5) The delete method is prefixed with remove/delete.
6) The modified method is prefixed with update.
B) Domain model naming convention
1) Data object: xxxDO, xxx is the data table name.
2) Data transmission object: xxxDTO, xxx is the name related to the business field.
7. No magic values (i.e. undefined constants) are allowed to appear directly in the code.
8. When assigning values to long or long, use upper case L after the value, not lower case L. lower case is easy to be confused with numbers, resulting in misunderstanding.
9. If it is empty in braces, simply write it as {}, and there is no need for line breaks and spaces in the middle of braces; If it is a non empty code block:
1) There is no newline before the left brace.
2) Wrap after left brace.
3) Wrap before closing brace.
4) If there are else and other codes after the right brace, there is no line break; A closing brace indicating termination must be followed by a newline.
10. Avoid accessing such static variables or static methods through the object reference of a class. There is no need to increase the parsing cost of the compiler. You can access them directly with the class name.
11. Any monetary amount is stored in the smallest monetary unit and integer type.
12. Distinguish the capitalized m and lowercase m in the date format, and the capitalized h and lowercase h refer to the meaning respectively. Note: the meanings of these two pairs of letters in the date format are as follows: 1) indicates that the month is capitalized m;
2) If it means minute, it is lowercase m;
3) The 24-hour system is capitalized H;
4) The 12 hour system is lowercase h.
13. The subList result of ArrayList cannot be forcibly converted to ArrayList, otherwise ClassCastException will be thrown: Java util. RandomAccessSubList cannot be cast to java. util. ArrayList.
14. Using the unique feature of the Set element, you can quickly de duplicate a Set, avoiding traversing and de duplication or judging inclusion by using the contents() of the List.
15. When multithreading processes scheduled tasks in parallel, when Timer runs multiple timetasks, as long as one of them does not catch the thrown exception, the other tasks will automatically terminate. There is no problem when using ScheduledExecutorService.
16. When velocity calls the property of POJO class, you can directly use the property name to get the value. The template engine will automatically call getXxx() of POJO according to the specification. If it is a boolean basic data type variable (boolean naming does not need to be prefixed with is), it will automatically call isXxx() method.
17. The RuntimeException defined in the Java class library that can be avoided by pre checking should not be handled by catch, such as NullPointerException, IndexOutOfBoundsException, etc. Note: exceptions that cannot pass the pre check are excluded. For example, when parsing a number in string form, there may be a number format error, which must be realized through catch NumberFormatException.
18. The warn log level can be used to record the error of user input parameters, so as to avoid being at a loss when users complain. If it is not necessary, please do not type the error level in this scenario to avoid frequent alarm.
19. Any parameter passed in by the user's request must be validated.
Note: ignoring parameter verification may result in:
⚫ Memory overflow caused by too large page size
⚫ Malicious order by causes slow database query
⚫ Buffer breakdown
⚫ SSRF
⚫ Arbitrary redirection
⚫ SQL injection, Shell injection, deserialization injection
⚫ Regular input source string denial of service ReDoS
Java code uses regular to verify the input of the client. Some regular writing methods have no problem verifying the input of ordinary users. However, if the attacker uses a specially constructed string to verify, it may lead to an endless loop.
20. The table must have three fields: id, gmt_create, gmt_modified.

Topics: Java