权限管理介绍

一个系统有多种角色的时候,每个人的权限,是不相同的,总不能对每一个部门写一个登录页面以及前台页面,而且每个部门每个人又有不同的等级,如果根据等级写页面呢是肯定不现实的

数据库的设计

根据角色授权的思想,我们需要五张表
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包

  1. <dependency>
  2. <groupId>org.apache.shiro</groupId>
  3. <artifactId>shiro-core</artifactId>
  4. <version>1.4.0</version>
  5. </dependency>

认证过程

构建securityManager环境

  1. DefaultSecurityManager defaultSecurityManager = new DefaultSecrityManager();
  2. defaultSecurityManager.setRealm(simpleAccountRealm);

主体提交认证请求

  1. SecurityUtils.setSecurityManager(defaultSecurityManager);
  2. Subject subject = SecurityUtils.getSubject();
  3. UsernamePasswordToKen token = new UsernamePassword(username : "小明"password :“123456”):
  4. subject.login(token);
  5. system.out.println("isAuthenticated:" + subject.isAuthenticated());
  6. subject.logout();
  7. system.out.println("isAuthenticated:" + subject.isAuthenticated());

以上两步骤是认证过程,以下是授权环境

授权过程

构建securitymanager环境

  1. DefaultSecurityManager defaultSecurityManager = new DefaultSecrityManager();
  2. defaultSecurityManager.setRealm(simpleAccountRealm);

主体提交认证请求

  1. SecurityUtils.setSecurityManager(defaultSecurityManager);
  2. Subject subject = SecurityUtils.getSubject();
  3. UsernamePasswordToKen token = new UsernamePassword(username : "小明"password :“123456”):
  4. subject.login(token);
  5. system.out.println("isAuthenticated:" + subject.isAuthenticated());
  6. subject.checkRole(s:"admin"); subject.checkRoles(...string:"admin","user");
  7. subject.logout();
  8. system.out.println("isAuthenticated:" + subject.isAuthenticated());

关于realm

realm一般分为三种,分别是
1)自定义
2)Inirealm控制.Ini文件
3)jdbcRealm控制,数据库文件
引入Mysql驱动包,引入数据源文件,设置jdbcurl以及用户名和密码

  1. JdbcRealm.jdbcRealm = new JdbcRealm();
  2. jdbcRealm.setDataSource(dataSource);
  3. jdbcRealm.setPermisssionsLookupEnabled(true);

主体提交验证

  1. subject.checkRole(s:"admin");
  2. subject.checkRoles(...string:"admin","user");
  3. subject.checkPermission(s:"user:select");

自定义realm

  1. package com.fuwh.realm;
  2. import java.sql.Connection;
  3. import java.sql.PreparedStatement;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import org.apache.shiro.authc.AuthenticationException;
  7. import org.apache.shiro.authc.AuthenticationInfo;
  8. import org.apache.shiro.authc.AuthenticationToken;
  9. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  10. import org.apache.shiro.authz.AuthorizationInfo;
  11. import org.apache.shiro.realm.AuthorizingRealm;
  12. import org.apache.shiro.subject.PrincipalCollection;
  13. import com.fuwh.util.DbUtil;
  14. public class MyJdbcRealm extends AuthorizingRealm{
  15. @Override
  16. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  17. // TODO Auto-generated method stub
  18. return null;
  19. }
  20. @Override
  21. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  22. // TODO Auto-generated method stub
  23. Connection conn=DbUtil.getConnection();
  24. String sql="select * from members2 where username=?";
  25. try {
  26. PreparedStatement ps=conn.prepareStatement(sql);
  27. ps.setString(1, token.getPrincipal().toString());
  28. ResultSet rs=ps.executeQuery();
  29. while(rs.next()) {
  30. AuthenticationInfo info=new SimpleAuthenticationInfo(rs.getString("username"),rs.getString("password"),"salt");
  31. return info;
  32. }
  33. } catch (SQLException e) {
  34. // TODO Auto-generated catch block
  35. e.printStackTrace();
  36. }
  37. return null;
  38. }
  39. }

关于MD5加密

环境搭建及使用

  1. CustomRealm customRealm = new CustomRealm();
  2. //1.构建SecurityManager 环境
  3. DefaultSecurityManager defaultSecurityManager = new DefaultSecrityManager();
  4. defalultSecurityManager.setRealm(customRealm);
  5. HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
  6. matcher.setHashAlgorithmName("md5");
  7. matcher.setHashIterations(1);
  8. customRealm.setCredentialsMatcher(matcher);
  9. //2.主体提交认证请求
  10. SecurityUtils.setSecurityManager(defaultSecurityManager);
  11. Subject subject = SecurityUtils.getSubject();
  12. UsernamePasswordToken token = new UsernamePassowrdToken(username:"xiaoming",password:"123456");
  13. subject.login(token);
  14. System.out.println("isAuthenticated:" + subject.isAuthenticated())

MD5加密

  1. @Override
  2. protected AuthenticationInfo doGetAuthenticationInfo(AuthticationToken authenticationToken) throws AuthenticationRxception {
  3. //1.从主体传过来的认证信息中,获取用户名
  4. String userName = StringauthenticationToken.getPrincipal();
  5. //2.通过用户名到数据库获取凭证
  6. String password = getPasswordByUserName(userName);
  7. if(password == null){
  8. return null;
  9. }
  10. SimpleAuthenticationInfo authticationInfo = new SimpleAuthenticationInfo (principal:“xiaoming”,password,realmName:"customRealm");
  11. authenticationInfo.setCredentialsSaltSalt(ByteSource.Util.bytes(string:"XQC"));
  12. return authenticationInfo;
  13. }

shiro在web项目中的的使用

本次采用spring+springmvc+mybatis实现的

执行流程

java实现权限组问题 - 图1

controller层控制

  1. package com.xqc.controller;
  2. //⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
  3. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡖⠒⠒⠤⢄⠀⠀
  4. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠁⠀⠀⠀⡼⠀⠀⠀⠀ ⠀
  5. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢶⣲⡴⣗⣲⡦⢤⡏⠀⠀⠀⠀⠀
  6. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⠋⠉⠉⠓⠛⠿⢷⣶⣦⠀⠀⠀
  7. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⠇⠀⠀⠀⠀⠀⠀⠘⡇⠀⠀⠀⠀
  8. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡞⠀⠀⠀⠀⠀⠀⠀⢰⠇⠀⠀⠀⠀
  9. // ⠀⠀⠀⠀⠀⠀⠀⠀⡴⠊⠉⠳⡄⠀⢀⣀⣀⡀⠀⣸⠀⠀⠀⠀⠀
  10. // ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠰⠆⣿⡞⠉⠀⠀⠉⠲⡏⠀⠀⠀⠀⠀
  11. // ⠀⠀⠀⠀⠀⠀⠀⠈⢧⡀⣀⡴⠛⡇⠀:⠃⠀⠀⡗⠀⠀⠀⠀⠀
  12. // ⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣱⠃⡴⠙⠢⠤⣀⠤⡾⠁⠀⠀⠀⠀⠀
  13. // ⠀⠀⠀⠀⠀⠀⠀⠀⢀⡇⣇⡼⠁⠀⠀⠀⠀⢰⠃⠀⠀⠀⠀⠀⠀
  14. // ⠀⠀⠀⠀⠀⠀⠀⠀⣸⢠⣉⣀⡴⠙⠀⠀⠀⣼⠀⠀⠀⠀⠀⠀⠀
  15. // ⠀⠀⠀⠀⠀⠀⠀⠀⡏⠀⠈⠁⠀⠀⠀⠀⢀⡇⠀⠀⠀⠀⠀⠀⠀
  16. // ⠀⠀⠀⠀⠀⠀⠀⢸⠃⠀⠀⠀⠀⠀⠀⠀⡼⠀⠀⠀⠀⠀⠀⠀⠀
  17. // ⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⣰⠃⠀⠀⠀⠀⠀⠀⠀⠀
  18. // ⠀⠀⠀⠀⠀⣀⠤⠚⣶⡀⢠⠄⡰⠃⣠⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀
  19. // ⠀⢀⣠⠔⣋⣷⣠⡞⠀⠉⠙⠛⠋⢩⡀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠀
  20. // ⠀⡏⢴⠋⠁⠀⣸⠁⠀⠀⠀⠀⠀⠀⣹⢦⣶⡛⠳⣄⠀⠀⠀⠀⠀
  21. // ⠀⠙⣌⠳ 小马无忧 ⡏⠀⠀⠈⠳⡌⣦⠀⠀⠀
  22. // ⠀⠀⠈⢳⣈⣻ ⢰⣇⣀⡠⠴⢊⡡⠋⠀⠀⠀⠀
  23. // ⠀⠀⠀⠀⠳⢿⡇⠀⠀⠀⠀⠀⠀⢸⣻⣶⡶⠊⠁⠀⠀
  24. // ⠀⠀⠀⠀⠀⢠⠟⠙⠓⠒⠒⠒⠒⢾⡛⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀
  25. // ⠀⠀⠀⠀⣠⠏⠀⣸⠏⠉⠉⠳⣄⠀⠙⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀
  26. // ⠀⠀⠀⡰⠃⠀⡴⠃⠀⠀⠀⠀⠈⢦⡀⠈⠳⡄⠀⠀⠀⠀⠀⠀⠀
  27. // ⠀⠀⣸⠳⣤⠎⠀⠀⠀⠀⠀⠀⠀⠀⠙⢄⡤⢯⡀⠀⠀⠀⠀⠀⠀
  28. // ⠀⠐⡇⠸⡅⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⡆⢳⠀⠀⠀⠀⠀⠀
  29. // ⠀⠀⠹⡄⠹⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣇⠸⡆⠀⠀⠀⠀⠀
  30. // ⠀⠀⠀⠹⡄⢳⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⡀⣧⠀⠀⠀⠀⠀
  31. // ⠀⠀⠀⠀⢹⡤⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣷⠚⣆⠀⠀⠀⠀
  32. // ⠀⠀⠀⡠⠊⠉⠉⢹⡀⠀⠀⠀⠀⠀⠀⠀⠀⢸⡎⠉⠀⠙⢦⡀⠀
  33. // ⠀⠀⠾⠤⠤⠶⠒⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠙⠒⠲⠤⠽⠀
  34. @Controller
  35. @RequestMapping("/blogger")
  36. public class BloggerController {
  37. @Resource
  38. private BloggerService bloggerService;
  39. /**
  40. * 用户登录
  41. * @param blogger
  42. * @param request
  43. * @return
  44. */
  45. @RequestMapping("/login")
  46. public String login(Blogger blogger,HttpServletRequest request){
  47. Subject subject=SecurityUtils.getSubject();
  48. UsernamePasswordToken token=new UsernamePasswordToken(blogger.getUserName(), CryptographyUtil.md5(blogger.getPassword(), "xqc"));
  49. try{
  50. subject.login(token); // 登录验证
  51. return "redirect:/admin/main.jsp";
  52. }catch(Exception e){
  53. e.printStackTrace();
  54. request.setAttribute("blogger", blogger);
  55. request.setAttribute("errorInfo", "用户名或密码错误!");
  56. return "login";
  57. }
  58. }
  59. }

spring配置文件中添加shiro过滤器

  1. <!-- Shiro过滤器 -->
  2. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  3. <!-- Shiro的核心安全接口,这个属性是必须的 -->
  4. <property name="securityManager" ref="securityManager"/>
  5. <!-- 身份认证失败,则跳转到登录页面的配置 -->
  6. <property name="loginUrl" value="/login.jsp"/>
  7. <!-- Shiro连接约束配置,即过滤链的定义 -->
  8. <property name="filterChainDefinitions">
  9. <value>
  10. /login=anon
  11. /admin/**=authc
  12. </value>
  13. </property>
  14. </bean>

拦截之后给自定义realm进行验证

  1. package com.xqc.realm;
  2. import javax.annotation.Resource;
  3. import org.apache.shiro.SecurityUtils;
  4. import org.apache.shiro.authc.AuthenticationException;
  5. import org.apache.shiro.authc.AuthenticationInfo;
  6. import org.apache.shiro.authc.AuthenticationToken;
  7. import org.apache.shiro.authc.SimpleAuthenticationInfo;
  8. import org.apache.shiro.authz.AuthorizationInfo;
  9. import org.apache.shiro.realm.AuthorizingRealm;
  10. import org.apache.shiro.subject.PrincipalCollection;
  11. import com.xqc.entity.Blogger;
  12. import com.xqc.service.BloggerService;
  13. /**
  14. * 自定义Realm
  15. *
  16. */
  17. public class MyRealm extends AuthorizingRealm{
  18. @Resource
  19. private BloggerService bloggerService;
  20. /**
  21. * 为当限前登录的用户授予角色和权
  22. */
  23. @Override
  24. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  25. return null;
  26. }
  27. /**
  28. * 验证当前登录的用户
  29. */
  30. @Override
  31. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
  32. String userName=(String)token.getPrincipal();
  33. Blogger blogger=bloggerService.getByUserName(userName);
  34. if(blogger!=null){
  35. SecurityUtils.getSubject().getSession().setAttribute("currentUser", blogger); // 当前用户信息存到session中
  36. AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(blogger.getUserName(),blogger.getPassword(),"xx");
  37. return authcInfo;
  38. }else{
  39. return null;
  40. }
  41. }
  42. }

使用工具类进行加密

  1. package com.xqc.util;
  2. import org.apache.shiro.crypto.hash.Md5Hash;
  3. /**
  4. * 加密工具
  5. *
  6. */
  7. public class CryptographyUtil {
  8. /**
  9. * Md5加密
  10. * @param str
  11. * @param salt
  12. * @return
  13. */
  14. public static String md5(String str,String salt){
  15. return new Md5Hash(str,salt).toString();
  16. }
  17. }