在Spring Boot+Spring Security框架里配置UserDetailsService

公司工作需要使用自建的云平台,虽然我是嵌入式工程师但是因为人手不足(主要还是建站的人走了,没人会Java)所以交由我来维护。

这次有了新需求,需要进行权限的分类和管理,由于原先的代码已经经了好几手了(心累啊!!),我需要保持原先的结构不动的情况下加入这些功能,那么原先的方式已经不满足需求了。

查阅了资料以后,决定直接使用UserDetailsService的形式对原先页面进行改造。

我们原先的spring-security.xml有如下代码:

<authentication-manager erase-credentials="false">
        <authentication-provider>
            <jdbc-user-service 
                data-source-ref="dataSource"
                users-by-username-query="select username,password,1 as enabled from sys_user where username=?"
                authorities-by-username-query="select u.username, r.name as role from sys_user u,sys_role_user ur, sys_role r where u.id=ur.Sys_User_id and r.id = ur.Sys_Role_id and u.username= ? "
             />  
       authentication-provider>
 authentication-manager>

这里的authentication-provider是使用了直接使用jdbc对数据库进行读取,但是在商业项目中我们不能将数据库结构直接暴露,所以我们要采用UserDetailsService的形式对于用户数据进行管理,同时也方便后期对于权限等地方的操作。

我们这里使用自定义的UserDetailsService来代替原先对数据库的直接操作:

<authentication-manager erase-credentials="false">
    <authentication-provider user-service-ref="myUserDetailsService">
    authentication-provider>
authentication-manager>

然后我们在后端,对myUserDetailsService这个类需要进行具体的设计,但是在此之前,我们需要自定义好UserDetails。

package com.hzmsc.scada.entity;

import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class User implements UserDetails{
/**   
 * @title: User
 * @author: zza
 * @date: 2020/3/9 17:05
 * @description: User用于权限验证和获取个人信息等方面,要注意和Users类的区别
*/
    private int id;
    private String username;
    private String password;
    private boolean enabled;
    private Collection<? extends GrantedAuthority> authorities;

    public User(int id, String username, String password, boolean enabled) {
        super();
        this.id = id;
        this.username = username;
        this.password = password;
        this.enabled = enabled;
    }

    public User(int id, String username, String password, boolean enabled,
                Collection<? extends GrantedAuthority> authorities) {
        super();
        this.id = id;
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.authorities = authorities;
    }
    public int getId(){
        return this.id;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }

    @Override
    public String toString() {
        return "MyUserDetails [id=" + id + ", username=" + username
                + ", password=" + password + ", enabled=" + enabled
                + ", authorities=" + authorities + "]";
    }
}

定义好User类以后我们就可以开始设计myUserDetailsService了。

package com.hzmsc.scada.service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import com.hzmsc.scada.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import javax.sql.DataSource;

public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    public void setDatasource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    JdbcTemplate jdbcTemplate;
    private final String sqlLoadUser;
    private final String sqlLoadAuthorities;
    private final RowMapper<User> myUserDetailsRowMapper;
    private final RowMapper<GrantedAuthority> authorityRowMapper;

    private static Logger logger = LoggerFactory
            .getLogger(MyUserDetailsService.class);

    public MyUserDetailsService(){
        super();
        sqlLoadUser ="select id,username,password,enabled from sys_user where username=?";
        sqlLoadAuthorities = "select r.name as role from sys_user u,sys_role_user ur, sys_role r where u.id=ur.Sys_User_id and r.id = ur.Sys_Role_id and u.username= ? ";
        
        myUserDetailsRowMapper = new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                return (new User(rs.getInt(1),
                        rs.getString(2),
                        rs.getString(3),
                        rs.getBoolean(4)));
            }

        };
        System.out.println();
        authorityRowMapper = new RowMapper<GrantedAuthority>() {
            @Override
            public GrantedAuthority mapRow(ResultSet rs, int rowNum)
                    throws SQLException {
                return new SimpleGrantedAuthority(rs.getString(1));
            }
        };
    }

    @Override
    public UserDetails loadUserByUsername(String username)

            throws UsernameNotFoundException {
        try {
            System.out.println("++++++++");
            User userFromQuery = jdbcTemplate.queryForObject(sqlLoadUser,
                    myUserDetailsRowMapper,username);
            logger.debug("查询得到用户:{}", userFromQuery);
            List<GrantedAuthority> authorities = jdbcTemplate.query(
                    sqlLoadAuthorities, authorityRowMapper, username);
            logger.debug("得到其权限:{}", authorities);
            return new User(userFromQuery.getId(), userFromQuery.getUsername(),
                    userFromQuery.getPassword(), userFromQuery.isEnabled(),
                    authorities);
        } catch (EmptyResultDataAccessException e) {
            logger.debug("查询结果集为空:{}", username);
            throw new UsernameNotFoundException("用户名或密码不正确");
        }
    }
}

注意开始的时候需要添加动态数据源,否则装配的时候会发生故障(-_-||这里被坑死)。

你可能感兴趣的:(springboot,spring,Security)