一、自定义Realm
之前的例子都是将 用户 角色 权限等信息 写死在ini配置文件中,但实际项目中都是从数据库中读取这些数据信息的,不是从配置文件。所以要用到自定义Realm
1、新建数据库 有users表 roles表 权限表,其中用户表和角色表 是
多对一的关系(即一个角色可以有多个用户)角色表和权限表是一对多的关系(即一个角色可以有多个权限)
2、在pom中添加 jdbc mysql 驱动支持
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency>
3、新建个User实体
package com.guo.entity; public class User { private Integer id; private String userName; private String password; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } 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; } }
4、新建个UserDao
package com.guo.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.HashSet; import java.util.Set; import com.guo.entity.User; public class UserDao { // 通过用户名获取 密码 public User getByUserName(Connection con,String userName)throws Exception{ User resultUser=null; String sql="select * from t_user where userName=?"; PreparedStatement pstmt=con.prepareStatement(sql); pstmt.setString(1, userName); ResultSet rs=pstmt.executeQuery(); if(rs.next()){ resultUser=new User(); resultUser.setId(rs.getInt("id")); resultUser.setUserName(rs.getString("userName")); resultUser.setPassword(rs.getString("password")); } return resultUser; } // 通过用户名获取角色 public Set<String> getRoles(Connection con, String userName) throws Exception{ Set<String> roles=new HashSet<String>(); String sql="select * from t_user u,t_role r where u.roleId=r.id and u.userName=?"; PreparedStatement pstmt=con.prepareStatement(sql); pstmt.setString(1, userName); ResultSet rs=pstmt.executeQuery(); while(rs.next()){ roles.add(rs.getString("roleName")); } return roles; } //通过用户名获取权限 public Set<String> getPermissions(Connection con, String userName)throws Exception { Set<String> permissions=new HashSet<String>(); String sql="select * from t_user u,t_role r,t_permission p where u.roleId=r.id and p.roleId=r.id and u.userName=?"; PreparedStatement pstmt=con.prepareStatement(sql); pstmt.setString(1, userName); ResultSet rs=pstmt.executeQuery(); while(rs.next()){ permissions.add(rs.getString("permissionName")); } return permissions; } }
5、再新建一个包com.guo.realm MyReaml.java
package com.guo.realm; import java.sql.Connection; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import com.guo.dao.UserDao; import com.guo.entity.User; import com.guo.util.DbUtil; public class MyRealm extends AuthorizingRealm{ private UserDao userDao=new UserDao(); private DbUtil dbUtil=new DbUtil(); //登录成功后 为当前登录的用户授予角色和权限 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String userName=(String)principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo(); Connection con=null; try{ con=dbUtil.getCon(); authorizationInfo.setRoles(userDao.getRoles(con,userName));// 将从数据库中获取的角色设置给当前用户 authorizationInfo.setStringPermissions(userDao.getPermissions(con,userName)); }catch(Exception e){ e.printStackTrace(); }finally{ try { dbUtil.closeCon(con); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } return authorizationInfo; } // 首先先获取用户名密码 验证登录信息 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //获取前台用户提交的用户名,连带着密码也能获取到 String userName=(String)token.getPrincipal(); //前台提交的用户名和密码封装在token中 Connection con=null; try{ con=dbUtil.getCon(); //获取数据库连接 User user=userDao.getByUserName(con, userName); //调用UserDao的getByUserName从数据库中获取到用户名 if(user!=null){ // 如果从数据库中获取到的用户名不为空 //则连带着 密码 也获取到 AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xx"); return authcInfo;//返回一个认证信息,内部会将从数据库中获取的信息与用户前台传来的用户名密码进行比对 }else{ return null; } }catch(Exception e){ e.printStackTrace(); }finally{ try { dbUtil.closeCon(con); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } return null; } }
以上是没用框架的,以后会整合到框架中
6、常见错误
连数据库时会报如下错误
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
数据库连接失败
引入的jdbc mysql包版本是6.0.6的 后来换成5.1.38 错误消失