以前咱們完成了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);
再以前的基礎上又增長了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>
增長鏈接數據庫的相關配置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就沒什麼好說的了,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,用戶驗證和受權改成從數據庫中獲取數據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; } }
由於修改後的realm須要LoginService的支持,因此相應的調整SpringApplication,其餘地方不變。ide
@Bean public PropertiesRealm propertiesRealm(LoginService loginService) { return new PropertiesRealm(loginService); }