218.Spring Boot+Spring Security:基于内存数据库的身份认证和角色授权

Posted SpringBoot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了218.Spring Boot+Spring Security:基于内存数据库的身份认证和角色授权相关的知识,希望对你有一定的参考价值。

说明

(1)JDK版本: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

 

需求缘起

       在前面我们使用基于内存的方式体验了下Spring Security,在实际项目中,都是需要数据库进行操作的,本节使用hsqldb内存数据库进行说明。

 

编码思路

       这里我们使用的是Spring Data JPA进行操作数据库,所以需要添加相关的依赖;其次就是需要定义一个保存用户基本的实体类;再者需要定义相应的服务获取用户的信息;最后重写UserDetailsService的loadUserByUsername方法从数据库中获取用户信息,传给Spring Security进行处理。

 

一、基于内存数据库的身份认证和角色授权

1.1 添加依赖

       在pom.xml文件中添加SpringData JPA和hsqldb的依赖:

       <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 创建实体类

       创建UserInfo实体类:

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;//主键.

    private String username;//用户名.
    private String 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 创建Repository

       创建和数据库交互的UserInfoRepository:

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 创建Service

       创建UserInfoService:

package com.kfit.permission.service;

import com.kfit.permission.bean.UserInfo;

public interface UserInfoService {

    public UserInfo findByUsername(String username);

}

       创建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 自定义UserDetailsService

       自定义一个UserDetailsService,取名为CustomUserDetailService,该类需要实现接口UserDetailsService,主要是实现loadUserByUsername方法:

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()");
        //通过username获取用户信息
        UserInfo userInfo = userInfoService.findByUsername(username);
        if(userInfo == null) {
            throw new UsernameNotFoundException("not found");
        }


        //定义权限列表.
        List<GrantedAuthority> authorities = new ArrayList<>();
        // 用户可以访问的资源名称(或者说用户所拥有的权限) 注意:必须"ROLE_"开头
        authorities.add(new SimpleGrantedAuthority("ROLE_"+userInfo.getRole().name()));


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

}

说明:

(1)    通过username获取用户的信息。

(2)    定义一个User(实现了接口UserDetails)对象,返回用户的username,passowrd和权限列表。

(3)    需要注意,定义角色集的时候,需要添加前缀“ROLE_”。

(4)    这里的密码需要使用PasswordEncoder进行加密,否则会报“无效的凭证”。

 

1.6 初始化测试账号

       这里我们使用一个DataInit类,初始化两个账号admin/123和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 启动测试

(1)测试账号:user/123

http://127.0.0.1:8080/hello/helloUser

自动跳转到登录页面,输入账号user/123,可以看到页面:

http://127.0.0.1:8080/hello/helloAdmin

       访问被拒绝:

 

(2)测试账号:admin/123

历史文章




à悟空学院:http://t.cn/Rg3fKJD

学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!

SpringBoot视频:http://t.cn/R3QepWG

Spring Cloud视频:http://t.cn/R3QeRZc

SpringBoot Shiro视频:http://t.cn/R3QDMbh

SpringBoot交流平台:http://t.cn/R3QDhU0

SpringData和JPA视频:http://t.cn/R1pSojf

SpringSecurity5.0视频:http://t.cn/EwlLjHh

以上是关于218.Spring Boot+Spring Security:基于内存数据库的身份认证和角色授权的主要内容,如果未能解决你的问题,请参考以下文章

spring boot 之注解

Spring boot??????????????????Spring boot??????MySql,Mybatis???PageHelper??????

Spring Boot 事物回滚

使用 Spring Boot 时如何使用 SpringTemplateEngine

jboss spring boot

spring boot微服务通用部署启动脚本