Spring Boot+Spring Security: identity authentication and role authorization based on memory database

Explain

(1) JDK version: 1.8

(2)Spring Boot 2.0.6

(3)Spring Security 5.0.9

(4)Spring Data JPA 2.0.11.RELEASE

(5)hibernate5.2.17.Final

(6)hsqldb2.4.1

 

1, Identity authentication and role authorization based on memory database

1.1 add dependency

Add the dependency of SpringData JPA and hsqldb in pom.xml file:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.hsqldb</groupId>
            <artifactId>hsqldb</artifactId>
            <scope>runtime</scope>
        </dependency>

1.2 create entity class

To create a UserInfo entity class:

package com.kfit.permission.bean;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class UserInfo {

    public enum Role{
        admin,normal
    }


    @Id @GeneratedValue
    private long uid;//Primary key.

    private String username;//User name.
    private String password;//Password.

    @Enumerated(EnumType.STRING)
    private Role role;

    public long getUid() {
        return uid;
    }

    public void setUid(long uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Role getRole() {
        return role;
    }

    public void setRole(Role role) {
        this.role = role;
    }


} 

1.3 creating a Repository

To create a UserInfoRepository that interacts with a database:

package com.kfit.permission.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.kfit.permission.bean.UserInfo;

public interface UserInfoRepository extends JpaRepository<UserInfo,Long> {

    public UserInfo findByUsername(String username);

}

1.4 create Service

Create UserInfoService:

package com.kfit.permission.service;

import com.kfit.permission.bean.UserInfo;

public interface UserInfoService {

    public UserInfo findByUsername(String username);

}

To create an implementation class for UserInfoService:

package com.kfit.permission.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kfit.permission.bean.UserInfo;
import com.kfit.permission.repository.UserInfoRepository;
import com.kfit.permission.service.UserInfoService;

@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoRepository userInfoRepository;

    @Override
    public UserInfo findByUsername(String username) {
        return userInfoRepository.findByUsername(username);
    }

}

1.5 customize UserDetailsService

Customize a UserDetailsService named CustomUserDetailService. This class needs to implement the interface UserDetailsService, mainly the loadUserByUsername method:

package com.kfit.config;

import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import com.kfit.permission.bean.UserInfo;
import com.kfit.permission.service.UserInfoService;

@Component
public class CustomUserDetailService implements UserDetailsService{

    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("CustomUserDetailService.loadUserByUsername()");
        //Get user information through username
        UserInfo userInfo = userInfoService.findByUsername(username);
        if(userInfo == null) {
            throw new UsernameNotFoundException("not found");
        }


        //Define permission list
        List<GrantedAuthority> authorities = new ArrayList<>();
        // The name of the resource that the user can access (or the permission that the user has) Note: it must start with "ROLE"
        authorities.add(new SimpleGrantedAuthority("ROLE_"+userInfo.getRole().name()));


        User userDetails = new User(userInfo.getUsername(),passwordEncoder.encode(userInfo.getPassword()),authorities);
        return userDetails;
    }

}

 

Explain:

(1) Get the user's information through username.

(2) Define a user (implement the interface UserDetails) object, and return the user's username,passowrd and permission list.

(3) Note that when defining a character set, you need to add the prefix "ROLE".

(4) The password here needs to be encrypted with PasswordEncoder, otherwise "invalid certificate" will be reported.

 

1.6 initialize test account

Here we use a DataInit class to initialize two accounts admin/123 and user/123:

package com.kfit.permission.init;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kfit.permission.bean.UserInfo;
import com.kfit.permission.bean.UserInfo.Role;
import com.kfit.permission.repository.UserInfoRepository;

@Service
public class DataInit {

    @Autowired UserInfoRepository userInfoRepository;


    @PostConstruct
    public void dataInit() {

        UserInfo admin = new UserInfo();
        admin.setUsername("admin");
        admin.setPassword("123");
        admin.setRole(Role.admin);
        userInfoRepository.save(admin);


        UserInfo user = new UserInfo();
        user.setUsername("user");
        user.setPassword("123");
        user.setRole(Role.normal);
        userInfoRepository.save(user);
    }

}

1.7 create WebSecurityConfigurerAdapter to start Security annotation

package huangan.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  /*  @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder())
                .withUser("admin")
                .password("123456")
                .roles("admin");

        auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder())
                .withUser("user")
                .password("123456")
                .roles("normal");
    }*/
}

1.8 write access layer interface authorization

package huangan.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloController {

    @GetMapping
    public String getWelcomeMsg(){
        return "hrllo,Spring Security";
    }

    @GetMapping("/helloAdmin")
    @PreAuthorize("hasAnyRole('admin')")
    public String helloAdmin() {
        return "Hello,admin";
    }

    @GetMapping("/helloUser")
    @PreAuthorize("hasAnyRole('normal')")
    public String helloUser() {
        return "Hello,user";
    }
}

1.9 start up test

(1) Test account: user/123

Start app access address:

http://127.0.0.1:8080/hello/helloUser

Automatically jump to the login page, enter the account user/123, and you can see the page:

 

Next to the address:

http://127.0.0.1:8080/hello/helloAdmin

Access denied:

 

(2) Test account: admin/123

Now there is no exit button. You can only restart the application and enter the account admin/123. The above two addresses should be accessible normally.

 

Published 22 original articles, won praise 6, visited 185
Private letter follow

Keywords: Spring Database Java JDK

Added by ligraci on Sat, 14 Mar 2020 09:55:20 +0200