Springboot+springsecurity Processing AJAX Login Requests

Source: Internet
Author: User
Tags auth

Recently encountered a problem in the project: the front-end separation, the frontend with Vue, all the data requests are using Vue-resource, no form, so the data interaction is using JSON, the background using spring Boot, permission validation using the spring Security, because the previous use of spring security is the processing of the page, this time simply processing the AJAX request, so record some of the problems encountered. The solution here applies not only to Ajax requests, but also to mobile request validation.

This article is a question record of the V Tribe project in the process of completion, the complete project please the small partners here: Https://github.com/lenve/VBlog Create the project

First we need to create a Spring boot project that needs to be introduced into the web, spring Security, MySQL, and MyBatis (the database framework is in fact random, I use mybatis here), and after creation, the dependent files are as follows:

<dependency>    <groupId>Org.mybatis.spring.boot</groupId>    <artifactid>Mybatis-spring-boot-starter</artifactid>    <version>1.3.1</version></Dependency><dependency>    <groupId>Org.springframework.boot</groupId>    <artifactid>Spring-boot-starter-security</artifactid></Dependency><dependency>    <groupId>Org.springframework.boot</groupId>    <artifactid>Spring-boot-starter-web</artifactid></Dependency><dependency>    <groupId>Mysql</groupId>    <artifactid>Mysql-connector-java</artifactid>    <scope>Runtime</Scope></Dependency><dependency>    <groupId>Commons-codec</groupId>    <artifactid>Commons-codec</artifactid>    <version>1.11</version></Dependency>

Note that the last Commons-codec dependency I manually joined, this is an Apache open source project, can be used to generate MD5 message digest, I will be in the following text to the simple processing of the password.

Create a database and configure

To simplify the logic, I created three tables here, namely the user table, the role table, and the User Role association table, as follows:

Next we need to make a simple configuration of our own database in Application.properties, where the small partners are determined by their own circumstances.

spring.datasource.url=jdbc:mysql:///vueblogspring.datasource.username=rootspring.datasource.password=123
Constructing entity classes

Here mainly refers to the construction of the user class, where the user class is very special, must implement the Userdetails interface, as follows:

 Public  class User implements userdetails {    PrivateLong ID;PrivateString username;PrivateString password;PrivateString nickname;Private BooleanEnabledPrivatelist<role> roles;@Override     Public Boolean isaccountnonexpired() {return true; }@Override     Public Boolean isaccountnonlocked() {return true; }@Override     Public Boolean iscredentialsnonexpired() {return true; }@Override     Public Boolean isenabled() {returnEnabled }@Override     PublicList<grantedauthority>getauthorities() {list<grantedauthority> authorities =NewArraylist<> (); for(Role role:roles) {Authorities.add (NewSimplegrantedauthority ("Role_"+ Role.getname ())); }returnAuthorities; }//getter/setter omitted ...}

After implementing the Userdetails interface, there are several methods in this interface that need us to implement, four return Boolean method is known as the name, enabled to indicate whether the schedule account is enabled, this my database does have this field, so based on the query results returned, Other for the simple period are directly returned True,getauthorities method return the current user's role information, the user's role is actually the data in the roles, the roles in the data into a list after the return, there is a place to note, Because I store in the database the role name is such as ' Super Administrator ', ' ordinary user ' and so on, not to ROLE_ start with such characters, so need to manually add here ROLE_ , remember .

There is also a role entity class, relatively simple, according to the database of the field creation can, here no longer repeat.

Create UserService

Here the UserService is also more special, need to implement the Userdetailsservice interface, as follows:

@Service Public  class userservice implements userdetailsservice {    @AutowiredUsermapper Usermapper;@AutowiredRolesmapper Rolesmapper;@Override     PublicUserdetailsLoaduserbyusername(String s)throwsusernamenotfoundexception {User user = Usermapper.loaduserbyusername (s);if(User = =NULL) {//Avoid returning NULL, this returns a user object that does not contain any value, and the subsequent password will fail in the same way as in the procedure.            return NewUser (); }//Query the user's role information and return tolist<role> roles = Rolesmapper.getrolesbyuid (User.getid ()); User.setroles (roles);returnUser }}

After implementing the Userdetailsservice interface, we need to implement the Loaduserbyusername method in this interface, that is, to query the user based on the user name. This is injected with two mybatis mapper,usermapper to query the user, Rolesmapper to query the role. In the Loaduserbyusername method, the first is to query the user based on the parameters passed in (the parameter is the user name entered when the user logs in), if the user is found to be null, you can simply throw a usernamenotfoundexception exception, But in order to handle the convenience, I returned a user object without any value, so that in the following password than the process will find the login failed (here everyone according to their business needs adjustment can be), if the user is not NULL, then we look at the user ID to query the user's role, and put the query results into the user object, this query results will be used in the Getauthorities method of the user object.

Security Configuration

Let's take a look at my security configuration and then I'll come back with one by one explanations:

@Configuration Public  class websecurityconfig extends websecurityconfigureradapter {    @AutowiredUserService UserService;@Override    protected void Configure(Authenticationmanagerbuilder auth)throwsException {auth.userdetailsservice (userservice). Passwordencoder (NewPasswordencoder () {@Override             PublicStringencode(Charsequence charsequence) {returnDigestutils.md5digestashex (Charsequence.tostring (). GetBytes ()); }/** * @param charsequence plaintext * @param s ciphertext * @return */            @Override             Public Boolean matches(Charsequence charsequence, String s) {returnS.equals (Digestutils.md5digestashex (Charsequence.tostring (). GetBytes ()));    }        }); }@Override    protected void Configure(httpsecurity http)throwsException {http.authorizerequests (). Antmatchers ("/admin/**"). Hasrole ("Super admin"). Anyrequest (). Authenticated ()//Other paths are accessed after login. and (). Formlogin (). LoginPage ("/login_page"). Successhandler (NewAuthenticationsuccesshandler () {@Override             Public void onauthenticationsuccess(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, authentication Authentication)throwsIOException, servletexception {httpservletresponse.setcontenttype ("Application/json;charset=utf-8");                PrintWriter out = Httpservletresponse.getwriter (); Out.write ("{\" status\ ": \" Ok\ ", \" msg\ ": \" Login succeeded \ "}");                Out.flush ();            Out.close (); }}). Failurehandler (NewAuthenticationfailurehandler () {@Override                     Public void onauthenticationfailure(HttpServletRequest httpservletrequest, HttpServletResponse httpservletresponse, authenticationexception e)throwsIOException, servletexception {httpservletresponse.setcontenttype ("Application/json;charset=utf-8");                        PrintWriter out = Httpservletresponse.getwriter (); Out.write ("{\" status\ ": \" error\ ", \" msg\ ": \" Login failed \ "}");                        Out.flush ();                    Out.close (); }}). Loginprocessingurl ("/login"). Usernameparameter ("username"). Passwordparameter ("Password"). Permitall (). and (). Logout (). Permitall (). and (). CSRF (). disable (); }@Override     Public void Configure(Websecurity web)throwsException {web.ignoring (). Antmatchers ("/reg"); }}

This is the core of our configuration, the small partners listen to my one by one way:

1. First this is a configuration class, so remember to add @configuration annotations, and since this is the configuration of spring security, remember to inherit Websecurityconfigureradapter.
2. Inject the userservice you just created, and we'll use it in a few.
The 3.configure (Authenticationmanagerbuilder auth) method is used to configure our authentication method, passing in the UserService in the Auth.userdetailsservice () method, The Loaduserbyusername method in this userservice will be called automatically when the user logs on. The following passwordencoder is optional, can write not write, because I am the user's plaintext password generated MD5 message digest into the database, so at the login also need to handle the plaintext password, so added Passwordencoder, Add Passwordencoder, directly new a Passwordencoder anonymous inner class, here are two ways to implement, see the name to know the meaning of the method, the first method encode is obviously to encrypt the plaintext, here I used the MD5 message digest, The specific implementation method is provided by Commons-codec dependency, the second method matches is the password of the comparison, two parameters, the first parameter is clear text password, the second is ciphertext, here only need to clear the plaintext after encryption and ciphertext comparison can (small partner if interested in this can continue to consider the password add salt).
4.configure (httpsecurity http) is used to configure our authentication rules, etc., the Authorizerequests method means that the authentication rule configuration is turned on, Antmatchers ("/admin/**"). Hasrole (" Super admin ") indicates/admin/**The path needs to have the ' Super Administrator ' role of the user to access, I see on the Internet small partners on the Hasrole method to addROLE_Prefix in question, this is not added, if you use the Hasauthority method to add. Anyrequest (). Authenticated () indicates that all other paths require authentication/logon before they can be accessed. Next we configure the login page for login_page, login processing path is/login, login user name username, password for password, and configure these paths can be directly accessed, log off the login can also be directly accessed, and finally close csrf. In Successhandler, use response to return the JSON of successful login, remember that you can not use Defaultsuccessurl,defaultsuccessurl is the only page redirected after successful login. Failurehandler is also not using Failureurl for the same reason.
5.configure (websecurity Web) method I configured some filtering rules, do not repeat.
6. In addition, for static files, such as/images/**/css/**/js/**These paths, which are not intercepted by default here.

Controller

Finally, take a look at our controller, as follows:

 @RestController  public  class  loginregcontroller  { /** * If you automatically jump to this page, indicating that the user is not logged in, return the appropriate prompt *     <p> * If you want to support form login, you can determine the type of request in this method, and then decide whether to return JSON or HTML page * * @return  */  @RequestMapping  ( "/login_page" ) Span class= "Hljs-keyword" >public  respbean loginpage  () {return  new  respbean (" error ", Span class= "hljs-string" > "not logged in, please login!" );}  

This controller overall is relatively simple, respbean a response bean, return a simple JSON, do not repeat, here need to note that the login_page login page We configured is a login_page , but actually login_page not a page, Instead, it returns a JSON, because spring security automatically jumps to the page when I'm not logged in to the page login_page , but in an AJAX request, it's not required, and all I want is a sign-in hint, so here's the JSON.

Test

The last small partner can use tools such as Postman or restclient to test login and permissions issues, I will not demonstrate.

OK, after the introduction of the above, presumably small partners to Spring boot+spring security processing AJAX Login request has been understood, well, this article here, there are questions welcome message discussion.

This article is a question record of the V Tribe project in the process of completion, the complete project please the small partners here: Https://github.com/lenve/VBlog

For more information, please follow the public number:

Springboot+springsecurity Processing AJAX Login Requests

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.