权限管理介绍
一个系统有多种角色的时候,每个人的权限,是不相同的,总不能对每一个部门写一个登录页面以及前台页面,而且每个部门每个人又有不同的等级,如果根据等级写页面呢是肯定不现实的
数据库的设计
根据角色授权的思想,我们需要五张表
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{@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {// TODO Auto-generated method stubreturn null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {// TODO Auto-generated method stubConnection 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 blocke.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加密
@Overrideprotected 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 {@Resourceprivate 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{@Resourceprivate BloggerService bloggerService;/*** 为当限前登录的用户授予角色和权*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}/*** 验证当前登录的用户*/@Overrideprotected 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();}}
