Recently, I was working on an app project. I developed it alone in the background. The basic functions of login, registration and permission verification were not included in the first stage of development in the order of development tasks. Now some business-related functions have been completed, but the user portal has not yet been implemented. This only shows that I was too anxious when I first analyzed the requirements and put the most basic user portal behind.
Now you need to add user login and permission verification functions based on the existing code.
Regarding login and permission verification, referring to previous iOS development experience, the App side provides username and password to exchange for tokens, and login permission is required for each request through the exchanged token.
Now, on the other hand, I need to consider the following issues:
1. How to easily meet the implementation of these functions in the existing functions' code, so that the existing code is not much changed, and there will be no hassle to implement permission verification in the future.
2. How to generate tokens based on username and password, and how to distinguish the correctness of client providing tokens in functions that require permissions
First of all, facing the first problem, according to experience, the conventional solution is filters and interceptors. If login and permission verification are placed in the requirements arrangement, as long as the URLs of the later functions are given a certain pattern, the use of filters or interceptors will be successful. But now I am facing urls that have no design or specifications in the early stage, so I don't want to face using filters or interceptors.
In addition to the above conventional solutions, spring AOP has become a weapon to solve this type of problem. It uses face-tangent programming to provide a pre-notation for all methods that require permission verification. However, because the URL, class name or method is not regular, I thought of a custom annotation and verify permissions for all methods that add custom annotations.
1. Since you have already thought of using spring aop, the first step is to enable aop in the spring configuration file
//Open aop
<aop:aspectj-autoproxy />
The above configuration is based on pouring spring-aop-related jar packages into the project, and introducing the url of aop in the configuration file header.
2. Next, let’s define a custom annotation first
@Target({ElementType.METHOD, ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface UserAccess { }3. We cannot rush to do permission verification functions, because our token has not yet generated a solution.
In order token generation, single sign-on is considered, so tokens cannot be fixed all the time. Otherwise, at any time, as long as you have a token, you can use the same account at least two people at the same time, which is not allowed in our business at present. In the end, I chose "username + password + login time" to do MD5 encryption as a token (there are many methods, such as uuid when ensuring uniqueness and mutability). Generate tokens when the username and password are successfully verified, and save the token in the form of key-value pairs of "username:token" and "token:user" (can also be saved into the database), and finally return the token to the client.
The following code is just a simple example:
@Servicepublic class LoginService {/*** Store "User name: token" key-value pair */public static Map<String,String> tokenMap=new HashMap<String,String>();/*** Store "token:User" key-value pair */public static Map<String,User> loginUserMap=new HashMap<String,User>(); public String login(String name,String password){System.out.println(name+"-----"+password);/*** Check whether the login is successful* 1. Login successfully* 1.1. Successfully generate the corresponding token and update * 1.2. Throw an exception if it fails*/String token=tokenMap.get(name);User user=null;if(token==null){user=new User();user.setName(name);user.setPassword(password);System.out.println("New user login");}else{user=loginUserMap.get(token);loginUserMap.remove(token);System.out.println("Update user login token");}token=MD5Util.MD5(name+password+new Date().getTime());loginUserMap.put(token, user);tokenMap.put(name, token);System.out.println("Currently"+tokenMap.size()+"users");for(User u:loginUserMap.values()){System.out.println(u.getName()+":"+u.getPassword());}return token;} }4. At the same time, our client has obtained a token after logging in. As long as we carry the token in all requests that require permission, we can successfully obtain the response (suggestion: To facilitate app encoding, the token can be carried in the request header, and the existing code does not need to be major changes, and we do not need to care about token issues in the future). I just found a method to do an experiment:
@Controller@RequestMapping("/login")public class LoginController {@Autowiredprivate LoginService loginService; @UserAccess@RequestMapping(value="/loginin",method=RequestMethod.GET)public @ResponseBody String login(HttpServletRequest request){String name=request.getParameter("name");String password=request.getParameter("password");String token=loginService.login(name, password);return token;}}Note that the bold part is to customize the annotation. It is impossible to have tokens for the request parameters of the login function, so no matter how many times it is verified, it cannot be passed. Just make an example. @UserAccess add only works on the functionality that requires permission verification
5. Custom annotation is now a good entry point
@Component@Aspectpublic class PermissionAspect { //Set the custom annotation as the entry point @Before("@annotation(com.example.chap01.annotation.UserAccess)")public void checkPermission(JoinPoint joinPoint) throws Exception{System.out.println("Pre-notification");//Get intercepted request parameters Object[] args = joinPoint.getArgs();HttpServletRequest request=(HttpServletRequest)args[0];String token=request.getParameter("token");System.out.println("Pre-notification token:"+token);User user=LoginService.loginUserMap.get(token);if(user==null){System.out.println("Verification is not passed!");throw new Exception("No permission");}}}}At this point, the login and permission verification functions are all completed.
In addition, the source code on personal github is attached: https://github.com/zw201913/applogin.git
The above is all about this article, I hope it will be helpful to everyone's learning.