这一小节,我们将使用数据库中的数据,并自定义realm的形式,进行身份和权限的认证。
那我们依旧采用上节中用到的ShiroWeb项目
第一步:创建数据库的结构:
第二步:在pom.xml中添加mysql的驱动包
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
第三步:在项目中添加工具类,用于创建数据库连接,关闭数据库连接。
package com.java1234.util;
import java.sql.Connection;
import java.sql.DriverManager;
/**
* 数据库工具类
* @author
*
*/
public class DbUtil {
/**
* 获取数据库连接
* @return
* @throws Exception
*/
public Connection getCon() throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/db_shiro", "root", "root");
return con;
}
/**
* 关闭数据库连接
* @param con
* @throws Exception
*/
public void closeCon(Connection con)throws Exception{
if(con!=null){
con.close();
}
}
public static void main(String[] args) {
DbUtil dbUtil=new DbUtil();
try {
dbUtil.getCon();
System.out.println("数据库连接成功");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("数据库连接失败");
}
}
}
第四步:添加entity,用于封装数据库的数据信息,添加dao层,用于数据库的查询。
User.java
package com.java1234.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;
}
}
UserDao.java
package com.java1234.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.HashSet;
import java.util.Set;
import com.java1234.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;
}
}
第五步:自定义realm,用于身份认证,以及用户身份(角色+权限)授权
package com.java1234.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.SimpleAccount;
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.java1234.dao.UserDao;
import com.java1234.entity.User;
import com.java1234.util.DbUtil;
public class MyRealm extends AuthorizingRealm{
//userDao用于提供数据库数据
private UserDao userDao=new UserDao();
//dbUtil创建数据库连接,关闭
private DbUtil dbUtil=new DbUtil();
/**
* 为当前登录的用户授予角色和权限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取当前用户登录名
String userName=(String)principals.getPrimaryPrincipal();
//authorizationInfo存储用户认证信息
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();
Connection con=null;
try{
con=dbUtil.getCon();
//获取当前用户信息
User user=userDao.getByUserName(con, userName);
if(user!=null){
//该用户的数据库密码,与页面上传递过来的密码信息比较
//三个参数,用户数据库中的登录名,密码,以及realm的名字(可以随意定义)
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;
}
}
第六步:通过修改配置文件shiro.ini,向securityManager中注册自定义的realm
[main]
authc.loginUrl=/login
roles.unauthorizedUrl=/unauthorized.jsp
perms.unauthorizedUrl=/unauthorized.jsp
myRealm=com.java1234.realm.MyRealm
securityManager.realms=$myRealm
[urls]
/login=anon
/admin*=authc
/student=roles[teacher]
/teacher=pe硬编码rms["user:create"]
至于之前的[user][roles]等硬编码信息就可以删除了。
测试:
我们用java1234,123456进行登录,通过debug信息监测,授权信息。
通过ctrl+shirft+i(括起来后再使用快捷键:userDao.getRoles(con,userName)),监测到用户拥有的角色信息。
监测到的用户权限信息:
至此身份授权完成。
|