SpringBoot+Shiro+DB (二)

以前咱們完成了Spring+Shiro的最基本配置搭建,如今咱們再增長上DB,畢竟沒有哪一個系統會將用戶、角色、權限等信息硬編碼到代碼裏。DB選用myslq。java

數據庫準備

腳本以下。依然是兩個用戶:admin和guest。admin擁有角色admin以及權限permission一、permission2;guest擁有角色guest以及權限permission一、permission2。mysql

create table test.shiro_user (
       id int auto_increment primary key,
       username varchar(50),
       password varchar(50)
);

create table test.shiro_role (
       id int auto_increment primary key,
       role varchar(50)
);

create table test.shiro_permission (
       id int auto_increment primary key,
       permission varchar(50)
);

create table test.shiro_user_r_role (
       userid int,
       roleid int
);

create table test.shiro_user_r_permission (
       userid int,
       permissionid int
);

insert into test.shiro_user(id, username, password) values (1, 'admin', 'admin');
insert into test.shiro_user(id, username, password) values (2, 'guest', 'guest');

insert into test.shiro_role(id, role) values (1, 'admin');
insert into test.shiro_role(id, role) values (2, 'guest');

insert into test.shiro_permission(id, permission) values (1, 'permission1');
insert into test.shiro_permission(id, permission) values (2, 'permission2');
insert into test.shiro_permission(id, permission) values (3, 'permission3');
insert into test.shiro_permission(id, permission) values (4, 'permission4');

insert into test.shiro_user_r_role(userid, roleid) values (1, 1);
insert into test.shiro_user_r_role(userid, roleid) values (2, 2);

insert into test.shiro_user_r_permission(userid, permissionid) values (1, 1);
insert into test.shiro_user_r_permission(userid, permissionid) values (1, 2);
insert into test.shiro_user_r_permission(userid, permissionid) values (2, 3);
insert into test.shiro_user_r_permission(userid, permissionid) values (2, 4);

pom依賴

再以前的基礎上又增長了spring-jdbc和mysql的數據庫驅動,由於要鏈接數據庫嘛spring

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
</dependency>

application.properties

增長鏈接數據庫的相關配置sql

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.2.12:3306/test?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=onceas

Dao和Service

dao和service就沒什麼好說的了,Controller不用動數據庫

@Repository
public class LoginDao {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public LoginDao(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public List<User> getUserByUsername(String username) {
        String sql = "select id, username, password from shiro_user where username=?";
        return jdbcTemplate.query(sql, new Object[]{username}, new BeanPropertyRowMapper<User>(User.class));
    }

    public List<String> getRoleByUsername(String username) {
        String sql = "select role from shiro_role A " +
                "join shiro_user_r_role B on A.id = B.roleid " +
                "join shiro_user C on B.userid = C.id " +
                "where C.username=?";
        return jdbcTemplate.queryForList(sql, new Object[]{username}, String.class);
    }

    public List<String> getPermissionByUsername(String username) {
        String sql = "select permission from shiro_permission A " +
                "join shiro_user_r_permission B on A.id = B.permissionid " +
                "join shiro_user C on B.userid = C.id " +
                "where C.username=?";
        return jdbcTemplate.queryForList(sql, new Object[]{username}, String.class);
    }
}
@Service
public class LoginService {

    private final LoginDao loginDao;

    @Autowired
    public LoginService(LoginDao loginDao) {
        this.loginDao = loginDao;
    }

    public List<User> getUserByUsername(String username) {
        return loginDao.getUserByUsername(username);
    }

    public List<String> getRoleByUsername(String username) {
        return loginDao.getRoleByUsername(username);
    }

    public List<String> getPermissionByUsername(String username) {
        return loginDao.getPermissionByUsername(username);
    }
}

修改Realm

調整Realm,用戶驗證和受權改成從數據庫中獲取數據app

public class PropertiesRealm extends AuthorizingRealm {

    private final LoginService loginService;

    @Autowired
    public PropertiesRealm(LoginService loginService) {
        this.loginService = loginService;
    }

    // 用戶認證
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (authenticationToken instanceof UsernamePasswordToken) {
            UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
            String username = token.getUsername();
            String password = new String(token.getPassword());
            List<User> users = loginService.getUserByUsername(username);
            if (users == null || users.size() != 1) {
                throw new AuthenticationException("用戶名或密碼錯誤");
            }
            User user = users.get(0);
            if (!user.getPassword().equals(password)) {
                throw new AuthenticationException("用戶名或密碼錯誤");
            }
            return new SimpleAuthenticationInfo(username, password, getName());
        } else if (authenticationToken instanceof RememberMeAuthenticationToken) {
            RememberMeAuthenticationToken token = (RememberMeAuthenticationToken) authenticationToken;
            // TODO: 2018/10/24
            return null;
        } else if (authenticationToken instanceof HostAuthenticationToken) {
            HostAuthenticationToken token = (HostAuthenticationToken) authenticationToken;
            // TODO: 2018/10/24
            return null;
        } else {
            throw new AuthenticationException("未知的AuthenticationToken類型");
        }
    }

    // 用戶受權
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addRoles(loginService.getRoleByUsername(username));
        simpleAuthorizationInfo.addStringPermissions(loginService.getPermissionByUsername(username));
        return simpleAuthorizationInfo;
    }
}

調整SpringApplication

由於修改後的realm須要LoginService的支持,因此相應的調整SpringApplication,其餘地方不變。ide

@Bean
public PropertiesRealm propertiesRealm(LoginService loginService) {
    return new PropertiesRealm(loginService);
}
相關文章
相關標籤/搜索