权限管理介绍
一个系统有多种角色的时候,每个人的权限,是不相同的,总不能对每一个部门写一个登录页面以及前台页面,而且每个部门每个人又有不同的等级,如果根据等级写页面呢是肯定不现实的
数据库的设计
根据角色授权的思想,我们需要五张表
1)用户表
字段:id,用户名,密码
2)角色表
字段:id, 角色名,角色描述,
3)资源表:相当于权限表反正就是代表各种权限
字段:id, 资源标题,资源url
4)用户角色表(中间表)
字段:id, 用户id, 角色id
5)角色资源表(中间表)
字段: id ,角色id 资源id
使用shiro整合spring进行权限管理
shiro简介
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
Shiro 主要分为来个部分就是认证和授权,在个人感觉来看就是查询数据库做相应的判断而已。
导入jar包
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
认证过程
构建securityManager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecrityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToKen token = new UsernamePassword(username : "小明",password :“123456”):
subject.login(token);
system.out.println("isAuthenticated:" + subject.isAuthenticated());
subject.logout();
system.out.println("isAuthenticated:" + subject.isAuthenticated());
授权过程
构建securitymanager环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecrityManager();
defaultSecurityManager.setRealm(simpleAccountRealm);
主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToKen token = new UsernamePassword(username : "小明",password :“123456”):
subject.login(token);
system.out.println("isAuthenticated:" + subject.isAuthenticated());
subject.checkRole(s:"admin"); subject.checkRoles(...string:"admin","user");
subject.logout();
system.out.println("isAuthenticated:" + subject.isAuthenticated());
关于realm
realm一般分为三种,分别是
1)自定义
2)Inirealm控制.Ini文件
3)jdbcRealm控制,数据库文件
引入Mysql驱动包,引入数据源文件,设置jdbcurl以及用户名和密码
JdbcRealm.jdbcRealm = new JdbcRealm();
jdbcRealm.setDataSource(dataSource);
jdbcRealm.setPermisssionsLookupEnabled(true);
主体提交验证
subject.checkRole(s:"admin");
subject.checkRoles(...string:"admin","user");
subject.checkPermission(s:"user:select");
自定义realm
package com.fuwh.realm;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import com.fuwh.util.DbUtil;
public class MyJdbcRealm extends AuthorizingRealm{
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
Connection conn=DbUtil.getConnection();
String sql="select * from members2 where username=?";
try {
PreparedStatement ps=conn.prepareStatement(sql);
ps.setString(1, token.getPrincipal().toString());
ResultSet rs=ps.executeQuery();
while(rs.next()) {
AuthenticationInfo info=new SimpleAuthenticationInfo(rs.getString("username"),rs.getString("password"),"salt");
return info;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
关于MD5加密
环境搭建及使用
CustomRealm customRealm = new CustomRealm();
//1.构建SecurityManager 环境
DefaultSecurityManager defaultSecurityManager = new DefaultSecrityManager();
defalultSecurityManager.setRealm(customRealm);
HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
matcher.setHashAlgorithmName("md5");
matcher.setHashIterations(1);
customRealm.setCredentialsMatcher(matcher);
//2.主体提交认证请求
SecurityUtils.setSecurityManager(defaultSecurityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePassowrdToken(username:"xiaoming",password:"123456");
subject.login(token);
System.out.println("isAuthenticated:" + subject.isAuthenticated())
MD5加密
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthticationToken authenticationToken) throws AuthenticationRxception {
//1.从主体传过来的认证信息中,获取用户名
String userName = (String)authenticationToken.getPrincipal();
//2.通过用户名到数据库获取凭证
String password = getPasswordByUserName(userName);
if(password == null){
return null;
}
SimpleAuthenticationInfo authticationInfo = new SimpleAuthenticationInfo (principal:“xiaoming”,password,realmName:"customRealm");
authenticationInfo.setCredentialsSaltSalt(ByteSource.Util.bytes(string:"XQC"));
return authenticationInfo;
}
shiro在web项目中的的使用
本次采用spring+springmvc+mybatis实现的
执行流程
controller层控制
package com.xqc.controller;
//⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡖⠒⠒⠤⢄⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⠀⡼⠀⠀⠀⠀ ⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢶⣲⡴⣗⣲⡦⢤⡏⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠋⠉⠉⠓⠛⠿⢷⣶⣦⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠘⡇⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⠀⠀⢰⠇⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⡴⠊⠉⠳⡄⠀⢀⣀⣀⡀⠀⣸⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠰⠆⣿⡞⠉⠀⠀⠉⠲⡏⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠈⢧⡀⣀⡴⠛⡇⠀:⠃⠀⠀⡗⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣱⠃⡴⠙⠢⠤⣀⠤⡾⠁⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⣇⡼⠁⠀⠀⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⣸⢠⣉⣀⡴⠙⠀⠀⠀⣼⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⠀⡏⠀⠈⠁⠀⠀⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⣰⠃⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⠀⣀⠤⠚⣶⡀⢠⠄⡰⠃⣠⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⢀⣠⠔⣋⣷⣠⡞⠀⠉⠙⠛⠋⢩⡀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀
// ⠀⡏⢴⠋⠁⠀⣸⠁⠀⠀⠀⠀⠀⠀⣹⢦⣶⡛⠳⣄⠀⠀⠀⠀⠀
// ⠀⠙⣌⠳ 小马无忧 ⡏⠀⠀⠈⠳⡌⣦⠀⠀⠀
// ⠀⠀⠈⢳⣈⣻ ⢰⣇⣀⡠⠴⢊⡡⠋⠀⠀⠀⠀
// ⠀⠀⠀⠀⠳⢿⡇⠀⠀⠀⠀⠀⠀⢸⣻⣶⡶⠊⠁⠀⠀
// ⠀⠀⠀⠀⠀⢠⠟⠙⠓⠒⠒⠒⠒⢾⡛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⣠⠏⠀⣸⠏⠉⠉⠳⣄⠀⠙⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⠀⡰⠃⠀⡴⠃⠀⠀⠀⠀⠈⢦⡀⠈⠳⡄⠀⠀⠀⠀⠀⠀⠀
// ⠀⠀⣸⠳⣤⠎⠀⠀⠀⠀⠀⠀⠀⠀⠙⢄⡤⢯⡀⠀⠀⠀⠀⠀⠀
// ⠀⠐⡇⠸⡅⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⡆⢳⠀⠀⠀⠀⠀⠀
// ⠀⠀⠹⡄⠹⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠸⡆⠀⠀⠀⠀⠀
// ⠀⠀⠀⠹⡄⢳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡀⣧⠀⠀⠀⠀⠀
// ⠀⠀⠀⠀⢹⡤⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣷⠚⣆⠀⠀⠀⠀
// ⠀⠀⠀⡠⠊⠉⠉⢹⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡎⠉⠀⠙⢦⡀⠀
// ⠀⠀⠾⠤⠤⠶⠒⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠒⠲⠤⠽⠀
@Controller
@RequestMapping("/blogger")
public class BloggerController {
@Resource
private BloggerService bloggerService;
/**
* 用户登录
* @param blogger
* @param request
* @return
*/
@RequestMapping("/login")
public String login(Blogger blogger,HttpServletRequest request){
Subject subject=SecurityUtils.getSubject();
UsernamePasswordToken token=new UsernamePasswordToken(blogger.getUserName(), CryptographyUtil.md5(blogger.getPassword(), "xqc"));
try{
subject.login(token); // 登录验证
return "redirect:/admin/main.jsp";
}catch(Exception e){
e.printStackTrace();
request.setAttribute("blogger", blogger);
request.setAttribute("errorInfo", "用户名或密码错误!");
return "login";
}
}
}
spring配置文件中添加shiro过滤器
<!-- Shiro过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager"/>
<!-- 身份认证失败,则跳转到登录页面的配置 -->
<property name="loginUrl" value="/login.jsp"/>
<!-- Shiro连接约束配置,即过滤链的定义 -->
<property name="filterChainDefinitions">
<value>
/login=anon
/admin/**=authc
</value>
</property>
</bean>
拦截之后给自定义realm进行验证
package com.xqc.realm;
import javax.annotation.Resource;
import org.apache.shiro.SecurityUtils;
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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import com.xqc.entity.Blogger;
import com.xqc.service.BloggerService;
/**
* 自定义Realm
*
*/
public class MyRealm extends AuthorizingRealm{
@Resource
private BloggerService bloggerService;
/**
* 为当限前登录的用户授予角色和权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
return null;
}
/**
* 验证当前登录的用户
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String userName=(String)token.getPrincipal();
Blogger blogger=bloggerService.getByUserName(userName);
if(blogger!=null){
SecurityUtils.getSubject().getSession().setAttribute("currentUser", blogger); // 当前用户信息存到session中
AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(blogger.getUserName(),blogger.getPassword(),"xx");
return authcInfo;
}else{
return null;
}
}
}
使用工具类进行加密
package com.xqc.util;
import org.apache.shiro.crypto.hash.Md5Hash;
/**
* 加密工具
*
*/
public class CryptographyUtil {
/**
* Md5加密
* @param str
* @param salt
* @return
*/
public static String md5(String str,String salt){
return new Md5Hash(str,salt).toString();
}
}