使用shiro进行登录权限分配

Shiro 是一个 Apache 下的一开源项目项目,旨在简化身份验证和授权。

 

spring,springMVC,maven,shiro

 

shiro的配置,通过maven加入shiro相关jar包

 

第一步.shiro的配置,通过maven加入shiro相关jar包

   
          
            org.apache.shiro  
           shiro-core  
            1.2.1  
          
           
            org.apache.shiro  
           shiro-web  
             1.2.1  
           
          
             org.apache.shiro  
            shiro-ehcache  
            1.2.1  
           
          
             org.apache.shiro  
            shiro-spring  
             1.2.1  
          
 
  
第二步.web.xml中添加shiro过滤器

 


    
     
         contextConfigLocation
         classpath:application-context-*.xml
    
     
         org.springframework.web.context.ContextLoaderListener
     
     
    
        CharacterEncodingFilter
        org.springframework.web.filter.CharacterEncodingFilter
        
             encoding
           utf-8
         
     
     
         CharacterEncodingFilter
         /*
     
     
     
         shiroFilter
        org.springframework.web.filter.DelegatingFilterProxy
     
     
         shiroFilter
         /admin/*
     
     
     
         back
         org.springframework.web.servlet.DispatcherServlet
         
             contextConfigLocation
             classpath:springmvc.xml
         
     
     
         back
         *.action
     
     Archetype Created Web Application
 
第3步. spring中对shiro配置

 
     
     
         
         
          
        
          
         
        
         
        
         
             
                
                 
            
         
         
             
                 
                 /images/** = anon
                /js/** = anon
                /styles/** = anon
                
                 /validatecode.jsp = anon
                 
                 /admin/logout.do = logout
                 
                 
                
                 /welcome.jsp = user
                 /admin/index.do = user
                 
                 /** = authc
             
         
     
 
     
     
         
         
         
         
        
         
         
     

在上面的配置中每次开启了sessionManager都会出问题在这里将它注释掉了。

其次,上面中的配置也是将credentialsMatcher没有加入了,这种方式适用于没有对密码进行处理的情况。

其中CustomRealm的配置是重点。

第4步.

自定义Realm编码

                                                                                                                                                                                                                                                                                                                                                         
在上面的配置中每次开启了sessionManager都会出问题在这里将它注释掉了。


其次,上面中的配置也是将credentialsMatcher没有加入了,这种方式适用于没有对密码进行处理的情况。


其中CustomRealm的配置是重点。

第4步.自定义Realm编码

自定义Realm编码
CustomRealm如下:




public class CustomRealm extends AuthorizingRealm {
     // 设置realm的名称
    @Override
     public void setName(String name) {
         super.setName("customRealm");
     }
 
     @Autowired
     private AdminUserService adminUserService;


     /**
      * 认证
      */
     @Override
     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
 
         // token中包含用户输入的用户名和密码
         // 第一步从token中取出用户名
         String userName = (String) token.getPrincipal();
         // 第二步:根据用户输入的userCode从数据库查询
         TAdminUser adminUser = adminUserService.getAdminUserByUserName(userName);
        // 如果查询不到返回null
         if (adminUser == null) {//
            return null;
         }
         // 获取数据库中的密码
         String password = adminUser.getPassword();
         /**
          * 认证的用户,正确的密码
          */
        AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password, this.getName());
                //MD5 加密+加盐+多次加密
 //SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(adminUser, password,ByteSource.Util.bytes(salt), this.getName());
         return authcInfo;
     }


     /**
      * 授权,只有成功通过doGetAuthenticationInfo方法的认证后才会执行。
      */
     @Override
     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
         // 从 principals获取主身份信息
         // 将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),
        TAdminUser activeUser = (TAdminUser) principals.getPrimaryPrincipal();
         // 根据身份信息获取权限信息
        // 从数据库获取到权限数据
         TAdminRole adminRoles = adminUserService.getAdminRoles(activeUser);
         // 单独定一个集合对象
         List permissions = new ArrayList();
         if (adminRoles != null) {
             permissions.add(adminRoles.getRoleKey());
        }
         // 查到权限数据,返回授权信息(要包括 上边的permissions)
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
         // 将上边查询到授权信息填充到simpleAuthorizationInfo对象中
         simpleAuthorizationInfo.addStringPermissions(permissions);
         return simpleAuthorizationInfo;
     }
 
     // 清除缓存
     public void clearCached() {
         PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
         super.clearCache(principals);
     }
 }
第5步.缓存配置
ehcache.xml代码如下:

     
 
通过使用ehache中就避免第次都向服务器发送权限授权(doGetAuthorizationInfo)的请求。

6.自定义表单编码过滤器
CustomFormAuthenticationFilter代码,认证之前调用,可用于验证码校验
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {
     // 原FormAuthenticationFilter的认证方法
    @Override
     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
         // 在这里进行验证码的校验
 
         // 从session获取正确验证码
         HttpServletRequest httpServletRequest = (HttpServletRequest) request;
         HttpSession session = httpServletRequest.getSession();
         // 取出session的验证码(正确的验证码)
         String validateCode = (String) session.getAttribute("validateCode");
 
         // 取出页面的验证码
         // 输入的验证和session中的验证进行对比
         String randomcode = httpServletRequest.getParameter("randomcode");
         if (randomcode != null && validateCode != null && !randomcode.equals(validateCode)) {
             // 如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中
             httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");
             // 拒绝访问,不再校验账号和密码
             return true;
         }
         return super.onAccessDenied(request, response);
     }
 }

验证码代码:

validatecode.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
     pageEncoding="UTF-8"%>
 <%@ page import="java.util.Random"%>
 <%@ page import="java.io.OutputStream"%>
<%@ page import="java.awt.Color"%>
 <%@ page import="java.awt.Font"%>
<%@ page import="java.awt.Graphics"%>
<%@ page import="java.awt.image.BufferedImage"%>
<%@ page import="javax.imageio.ImageIO"%>
 <%
     int width = 60;
     int height = 32;
     //create the image
     BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
     Graphics g = image.getGraphics();
     // set the background color
     g.setColor(new Color(0xDCDCDC));
     g.fillRect(0, 0, width, height);
     // draw the border
    g.setColor(Color.black);
     g.drawRect(0, 0, width - 1, height - 1);
    // create a random instance to generate the codes
     Random rdm = new Random();
     String hash1 = Integer.toHexString(rdm.nextInt());
     // make some confusion
    for (int i = 0; i < 50; i++) {
         int x = rdm.nextInt(width);
        int y = rdm.nextInt(height);
         g.drawOval(x, y, 0, 0);
     }
     // generate a random code
     String capstr = hash1.substring(0, 4);
     //将生成的验证码存入session
     session.setAttribute("validateCode", capstr);
     g.setColor(new Color(0, 100, 0));
     g.setFont(new Font("Candara", Font.BOLD, 24));
     g.drawString(capstr, 8, 24);
     g.dispose();
     //输出图片
     response.setContentType("image/jpeg");
     out.clear();
     out = pageContext.pushBody();
     OutputStream strm = response.getOutputStream();
     ImageIO.write(image, "jpeg", strm);
     strm.close();
 %>


你可能感兴趣的:(java实现登录权限分配)