如何正确的使用shiro

从来没接触过shiro Java安全框架,突然有一天需要要用用户登陆验证和用户角色权限的任务,而且是针对shiro 进行整合,开始收到任务,心都有点凉凉的。经过一轮的搜索,感觉没多大的收获。很多用户的角色都是写在xml配置文件中。觉得太不人性化了,想换个用户角色还得改xml?我觉得这么强大的框架应该不可能这么狗血的存在。然后认真的看文档,发现真的是可以直接读取数据库的。我把我搭建的流程发布在此。有问题的可以交流交流。我写的也并不是正确的,只能参考参考。

1.web.xml的配置


   org.apache.shiro.web.env.EnvironmentLoaderListener


	shiroFilter
	org.apache.shiro.web.servlet.ShiroFilter


	shiroFilter
	/*

2.shiro.ini配置

[main]

[filters]

#自定义realm
shiroAuthorizingRealm = com.frame.security.ShiroAuthorizingRealm
securityManager.realm = $shiroAuthorizingRealm

# 声明一个自定义的用户校验拦截器
customFormAuthenticationFilter = com.frame.security.CustomFormAuthenticationFilter
# 声明一个自定义的用户角色权限拦截器
customPermissionsAuthorizationFilter = com.frame.security.CustomPermissionsAuthorizationFilter

#cache
shiroCacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
shiroCacheManager.cacheManagerConfigFile = classpath:ehcache.xml
securityManager.cacheManager = $shiroCacheManager

#session
sessionDAO = org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.sessionDAO = $sessionDAO
securityManager.sessionManager = $sessionManager
securityManager.sessionManager.globalSessionTimeout = 1800000

securityManager = org.apache.shiro.web.mgt.DefaultWebSecurityManager


[urls]
/admin/user/login = anon
/admin/user/logout = anon
/admin/user/registered = anon
/admin/** = customFormAuthenticationFilter,customPermissionsAuthorizationFilter

从shiro.ini配置中可以看出,需要三个文件,分别为ShiroAuthorizingRealm.java(realm文件),CustomFormAuthenticationFilter.java(自定义用户登陆验证文件),CustomPermissionsAuthorizationFilter(自定义用户角色权限文件);

在urls配置中可以看出不需要拦截的url后面加上anon便可,但有先后顺序。

缓存是使用ehcache

3.ehcache.xml配置

4.ShiroAuthorizingRealm.java

public class ShiroAuthorizingRealm extends AuthorizingRealm {
	private AuthorityService authorityService = FrameContext.getBean(AuthorityService.class);
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("=======doGetAuthenticationInfo=======");
        UsernamePasswordToken userToken = (UsernamePasswordToken) token;

        String username = userToken.getUsername();
        String password = String.valueOf(userToken.getPassword());
        User user = User.dao.findFirst("select * from m_user where account = ?", username);
        if (user != null) {//下面可以做一些登陆的操作,密码错误,用户状态等等
        	if(MD5Encoder.validPassword(password, user.getPassword())==false){
        		throw new UnknownAccountException();
            }
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
            return info;
        } else {
            return null;
        }
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("=======doGetAuthorizationInfo=======");
        User user = (User) principals.getPrimaryPrincipal();
        if(user!=null){//从数据库中读取用户的角色权限,
        	SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        	List perms = authorityService.getUrlByUser(user);
        	if(perms!=null&&perms.size()>0){//调用addStringPermissions方法把用户的权限添加到info中,可调用addRoles方法把用户的角色添加到info中
        		info.addStringPermissions(perms);
        	}
        	return info;
        }
        return null;
    }
}

5.CustomFormAuthenticationFilter.java

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter   {
    private final static Logger log = Logger.getLogger(CustomFormAuthenticationFilter.class);
    private static final String contentType = "application/json; charset=UTF-8";
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpRequest = WebUtils.toHttp(request);
        HttpServletResponse httpResponse = WebUtils.toHttp(response);
        if (isLoginRequest(request, response)) {
            if (isLoginSubmission(request, response)) {
                if (log.isTraceEnabled()) {
                    log.trace("Login submission detected.  Attempting to execute login.");
                }
                return executeLogin(request, response);
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Login page view.");
                }
                return true;
            }
        } else {
            Result result = new Result(false, "401", "没有授权,请先登录", null);
            renderJson(httpResponse, result);
            return false;
        }          
    }

    private void renderJson(HttpServletResponse response, Object object) {
        String jsonText = JsonKit.toJson(object);
        PrintWriter writer = null;
        try {
            response.setHeader("Pragma", "no-cache");   // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType(contentType);
            writer = response.getWriter();
            writer.write(jsonText);
            writer.flush();
        } catch (IOException e) {
            throw new RenderException(e);
        }
        finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}

 

6.CustomPermissionsAuthorizationFilter.java

 

public class CustomPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {
	private static final String contentType = "application/json; charset=UTF-8";
	private AuthorityService authorityService = McmsContext.getBean(AuthorityService.class);
	
	@Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
		if(getMappedValue(request)!=null){
			return super.isAccessAllowed(request, response, getMappedValue(request));
		}
		return false;
        
    }
	
	
	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
		// TODO Auto-generated method stub
		
		HttpServletRequest httpRequest = WebUtils.toHttp(request);
		HttpServletResponse httpResponse = WebUtils.toHttp(response);
		String path = httpRequest.getServletPath();
		Subject subject = getSubject(request, response);
		if (subject.isPermitted(path)) {
			return true;
		} else {
			Result result = new Result(false, "401", "抱歉,您没有该权限!", null);
			renderJson(httpResponse, result);
			return false;
		}
        
	}
	

    /**
     * 得到mappedValue,相当于perms[user:add]中的“user:add”
     * @param path
     * @return
     */
    public String[] getMappedValue(ServletRequest request) {
        HttpServletRequest req = (HttpServletRequest) request;
        String path = req.getServletPath();
        String code = getCodesByPath(path);
        if(null == code) {
            return null;
        }
        return new String[]{code};
    }

    /**
     * 根据访问路径获取权限代码
     * @param path
     * @return
     */
    public String getCodesByPath(String path) {
    	User user = (User) SecurityUtils.getSubject().getPrincipal();
    	String pers = authorityService.getUrlByUserPath(path,user);
        return Optional.ofNullable(pers).orElse(null);
    }
    
    private void renderJson(HttpServletResponse response, Object object) {
        String jsonText = JsonKit.toJson(object);
        PrintWriter writer = null;
        try {
            response.setHeader("Pragma", "no-cache");   // HTTP/1.0 caches might not implement Cache-Control and might only implement Pragma: no-cache
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            response.setContentType(contentType);
            writer = response.getWriter();
            writer.write(jsonText);
            writer.flush();
        } catch (IOException e) {
            throw new RenderException(e);
        }
        finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}

7.用户登陆入口

public void login() {
      String account = getPara("account");
      String password = getPara("password");
      Subject subject = SecurityUtils.getSubject();
      UsernamePasswordToken tokens = new UsernamePasswordToken(account, password);
      tokens.setRememberMe(false);
      try {
          subject.login(tokens);
          User user = (User) subject.getPrincipal();
          loginSuccess(user);
          UserVo userVo = convertToUserVO(user);
          renderSucessResult(userVo);
      } catch (UnknownAccountException ue) {
    	  tokens.clear();
          renderFailedResult("登录失败!无效的账号或密码!");
      } catch (IncorrectCredentialsException ie) {
    	  tokens.clear();
          renderFailedResult("用户已注销!");
      } catch(LockedAccountException le){
    	  tokens.clear();
          renderFailedResult("账号被锁定!");
      } catch (RuntimeException re) {
          re.printStackTrace();
          tokens.clear();
          renderFailedResult("登录失败!");
      }
      
}

8.项目使用maven


	org.apache.shiro
	shiro-core
	1.3.0


	org.apache.shiro
	shiro-web
	1.3.0


	org.apache.shiro
	shiro-ehcache
	1.3.0

 

数据库可以自己去设计,这里就不提供了。

 

参照上面的去整合框架,便可以使用了,这样搭建适合多种框架的整合!有问题可以留言!

你可能感兴趣的:(shiro)