1、简述

    1、1    Apache Shiro是Java的一个安全框架。是一个相对简单的框架,主要功能有认证、授权、加密、会话管理、与Web集成、缓存等。

    1、2   Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。

2、ssm集成shiro

    2、1  pom.xml文件中添加依赖

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>

    2、2  新建shiro配置文件spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config />
<context:component-scan base-package="com.hbst.basessm_1" /> <!-- proxy-target-class="true"强制使用CGLib代理,为false则spring会自动选择,否则事务不生效 -->
<aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 配置relam jdbc当调用验证时会调用此对象去查数据 -->
<bean id="myShiroService" class="com.hbst.basessm_1.shiro.MyShiroService"></bean>
<bean id="authzPathFilter" class="com.hbst.basessm_1.shiro.ShiroAuthzPathFilter"></bean> <!-- 配置权限管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myShiroService" />
<property name="cacheManager" ref="cacheManager" />
</bean> <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager" />
<!-- 配置我们的登录请求地址 -->
<property name="loginUrl" value="/" />
<!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址 -->
<property name="successUrl" value="/main" />
<!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
<property name="unauthorizedUrl" value="/" />
<!-- 权限配置 -->
<!-- /view/**=authc,perms[READS] -->
<property name="filterChainDefinitions">
<value>
/=anon
/js/**=anon
/theme/**=anon
/main=authc
/view/**=authc
</value>
</property>
</bean> <!-- bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManager" ref="cacheManager"/> </bean --> <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" /> <!-- 配置shiro bean生命周期管理类 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans>

    2、3  在web.xml中,加入spring-shiro.xml,将shiro的配置加入项目的上下文环境中

    

    2、4  在web.xml中,配置shiro安全过滤器

<!-- shiro配置 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

3、实现登录认证和授权

  3、1  到这里,ssm和shiro的整合就完成了,下面,我们使用shiro完成登录认证,首先,先创建一张user表,并插入一条记录

  

    为了简单,我这里使用明文密码,使用加密只需要在接收到前台提交的密码之后使用加密算法加密即可

  3、2 创建UserController.java

package com.hbst.basessm_1.controller;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import com.hbst.basessm_1.pojo.request.LoginParamRequest;
import com.hbst.basessm_1.service.IUserService;
import com.hbst.basessm_1.util.baseUtil.ResourceUtils;
import com.hbst.basessm_1.util.constant.CodeConstant;
import com.hbst.basessm_1.util.entity.ResultMessage;
import com.hbst.basessm_1.util.exception.BusinessException;
import com.hbst.basessm_1.util.log.ISCLog;
import com.hbst.basessm_1.util.log.impl.SCLogger; import net.sf.json.JSONObject; /**
* @author Dean
*/
@Controller
@RequestMapping("/user")
public class UserController { private static final ISCLog logger = new SCLogger(UserController.class);
@Resource
private IUserService userService; /**
*
* @return
*/
@ResponseBody
@RequestMapping(value = "/queryUser.do", method = RequestMethod.POST)
public Object queryUser(LoginParamRequest request, BindingResult result) {
logger.begin();
ResultMessage message = new ResultMessage();
try {
// 进行登录验证
Subject subject = SecurityUtils.getSubject();
//获取登录的用户名密码
String userName = request.getUserName();
String password = request.getPassword();
//生成令牌,此处可以使用令牌来实现记住我的功能
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
//token.setRememberMe(true);
//认证,
subject.login(token);
//判断是否通过验证
if (subject.isAuthenticated()) {
logger.debug("User Login Succeed", userName);
message.setCode(CodeConstant.SUCCESS);// 成功的状态码
logger.end();
}
} catch (BusinessException e) {
JSONObject json = new JSONObject();
message.setCode(e.getErrorCode());
message.setCodeDesc(e.getErrorDes());
logger.error(e);
} catch (Exception e) {
message.setCode(CodeConstant.SYSTEM_ERROR);
message.setCodeDesc(ResourceUtils.getResultCodeDesc(CodeConstant.SYSTEM_ERROR));
logger.error(e);
}
logger.end();
return message;
} }

    3、3  创建MyShiroService.java,这个java类是我们的realm,声明在spring-shiro.xml文件中,realm中有doGetAuthorizationInfo方法用于授权,doGetAuthenticationInfo方法用于登录认证

package com.hbst.basessm_1.shiro;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map; 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.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service; import com.hbst.basessm_1.service.IUserService;
import com.hbst.basessm_1.util.log.impl.SCLogger; import net.sf.json.JSONObject; @Service
@Scope("prototype")
public class MyShiroService extends AuthorizingRealm { private static final SCLogger logger = new SCLogger(MyShiroService.class); private UserManage userManage = null;
@Autowired
private IUserService userService;
/**
* 授权方法
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
logger.begin(); try {
// 获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next()
String loginName = (String) super.getAvailablePrincipal(principalCollection);
logger.debug("AuthorizationInfo Login Account", loginName); Map<String, Object> parameterMap = new HashMap<String, Object>();
parameterMap.put("userAccount", loginName);
logger.debug("userAccount parameterMap", parameterMap); // 到数据库查是否有此用户
JSONObject userObject = userService.queryLoginUserAccount(parameterMap);
userManage = (UserManage) JSONObject.toBean(userObject, UserManage.class);
logger.debug("queryLoginUserAccount Result", userManage); if (null != userManage ) {
if(userManage.getLockStatus()==0){
// 权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 获取用户角色列表
info.addRole(userManage.getUserType().toString());
logger.debug("Set User Roles", userManage.getUserType().toString()); // 获取权限列表
ArrayList<String> perListObject = userService.queryLoginUserPermission(parameterMap);
logger.debug("queryLoginUserPermission Result", perListObject); info.addStringPermissions(perListObject);
logger.debug("Get Module Permissions", perListObject.toString()); logger.end();
return info;
}else{ }
}
logger.end();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
/**
* 登录认证方法
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
logger.begin(); // UsernamePasswordToken对象用来存放提交的登录信息
UsernamePasswordToken token = (UsernamePasswordToken) arg0;
logger.debug("Token User Name", token.getUsername());
try {
Map<String, Object> parameterMap = new HashMap<String, Object>();
parameterMap.put("userName", token.getUsername());
parameterMap.put("userPassword", token.getPassword()); // 到数据库查是否有此对象
JSONObject userManageJsonObject = userService.queryUser(parameterMap);
if (null == userManageJsonObject || userManageJsonObject.isEmpty()) {
logger.error("INVALID USER ACCOUNT|" + token.getUsername());
throw new UnknownAccountException("用户名或者密码错误");
} userManage = (UserManage) JSONObject.toBean(userManageJsonObject, UserManage.class);
if (null == userManage) {
logger.error("INVALID USER ACCOUNT|" + token.getUsername());
throw new UnknownAccountException("用户名或者密码错误");
} String userName = userManage.getUserName().toLowerCase();
String userPassword = userManage.getPassword();
logger.debug("Query User Account", userName + "|" + userPassword); // 若存在,将此用户存放到登录认证info中
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName, userPassword, getName());
logger.debug("User Login Verify Succeed", userName);
logger.end();
return info;
} catch (UnknownAccountException e) {
// 用户名未知
logger.error(e.getMessage(), e);
throw e;
} catch (IncorrectCredentialsException e) {
// 凭据不正确,例如密码不正确
logger.error(e.getMessage(), e);
throw e;
} catch (AuthenticationException e) {
// 其他未指定异常
logger.error(e.getMessage(), e);
throw e;
} catch (Exception e) {
} logger.end();
return null;
}
}

    3、4 创建接口IUserService.xml

package com.hbst.basessm_1.service;

import net.sf.json.JSONObject;

/**
*
*/
public interface IUserService { /**
* 查询用户
* @return
*/
public abstract JSONObject queryUser(Object jsonParameter) throws Exception; }

    3、5  创建实现类UserService.java,这个类是真正用于与数据库交互,查询数据用的,下面的代码只实现了认证查询用户的方法,没有实现授权查询角色权限的方法

package com.hbst.basessm_1.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import com.hbst.basessm_1.dao.IBaseDao;
import com.hbst.basessm_1.pojo.User;
import com.hbst.basessm_1.service.IUserService;
import com.hbst.basessm_1.util.baseUtil.StringUtil;
import com.hbst.basessm_1.util.constant.CodeConstant;
import com.hbst.basessm_1.util.constant.CommonConstant;
import com.hbst.basessm_1.util.exception.BusinessException;
import com.hbst.basessm_1.util.log.ISCLog;
import com.hbst.basessm_1.util.log.impl.SCLogger; import net.sf.json.JSONObject; /**
* 用户实现类
*/
@Service("userService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class UserServiceImpl implements IUserService{ private static final ISCLog logger = new SCLogger(UserServiceImpl.class); @Autowired
private IBaseDao baseDao; /**
*
* 查询用户是否存在
* @return
*/
@Override
public JSONObject queryUser(Object jsonParameter) throws Exception {
logger.begin();
if (StringUtil.isEmpty(jsonParameter)) {
throw new BusinessException(CodeConstant.PARAMS_ERROR);
}
logger.debug("Parameter is:", jsonParameter);
//检查参数是否为空
// 检查参数是否存在且符合不允许为空的规则
JSONObject jsonObject = JSONObject.fromObject(jsonParameter);
// 获取参数,确保参数的正确性
User user = (User) baseDao.findOneByCustom("selectUser", jsonObject); JSONObject resultJsonObject = JSONObject.fromObject(user); logger.debug("Object Conversion Json Result:", resultJsonObject.toString());
logger.end();
return resultJsonObject;
} }

    3、6   页面js

      3、6、1  登录请求方法

            // 异步提交表单
$.ajax({
url:"${pageContext.request.contextPath}/user/queryUser.do",
dataType : "json",
data: {'userName': name,'password':pwd},
cache: false,
type: "POST",
success : function(data){
if(data.code=="000000"){
window.location.replace("${pageContext.request.contextPath}/main.jsp");
}else{
if (undefined != data.codeDesc){
alert(data.codeDesc);
}else{
alert("无效的登录用户名或密码!");
}
}
}
});

    3、6、2 授权页面

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<jsp:include page="../Main/include_head.jsp"></jsp:include>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<!DOCTYPE html>
<html>
<head lang="en">
</head>
<body>
<section class="content-header">
<h1>
<small>test</small>
</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i>test</a></li>
<shiro:hasPermission name="user:create">
<li><a href="#">test</a></li>
</shiro:hasPermission>
</ol>
</section> <!-- Main content --> </body> </html>

    3、7,流程说明

      3、7、1:认证流程说明

      登录认证,首先由前端页面发出请求,controller获取到前端提交的用户名和密码,生成令牌,然后调用subject.login(token)方法,此方法会先调用realm中的doGetAuthenticationInfo方法进行认证。认证成功跳转到配置文件中配置的跳转页面

      3、7、2:授权流程说明

      用户授权,会调用realm中的doGetAuthorizationInfo方法。调用此方法的方式有三种:   

        1、subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什么角色或者是否有什么权限的时候;

        2、@RequiresRoles("admin") :在方法上加注解的时候;

        3、[shiro:hasPermission name = "admin"] :在页面上加shiro标签的时候,即进这个页面的时候扫描到有这个标签的时候。如果在页面上使用shiro标签,

           必须在头部加上<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

ssm整合shiro—实现认证和授权的更多相关文章

  1. Spring Boot 整合 Shiro实现认证及授权管理

    Spring Boot Shiro 本示例要内容 基于RBAC,授权.认证 加密.解密 统一异常处理 redis session支持 介绍 Apache Shiro 是一个功能强大且易于使用的Java ...

  2. SpringBoot整合Shiro完成认证

    三.SpringBoot整合Shiro思路 首先从客户端发来的所有请求都经过Shiro过滤器,如果用户没有认证的都打回去进行认证,认证成功的,再判断是否具有访问某类资源(公有资源,私有资源)的权限,如 ...

  3. 使用Shiro实现认证和授权(基于SpringBoot)

    Apache Shiro是一个功能强大且易于使用的Java安全框架,它为开发人员提供了一种直观,全面的身份验证,授权,加密和会话管理解决方案.下面是在SpringBoot中使用Shiro进行认证和授权 ...

  4. SSM整合shiro

    采用maven构建项目 1pom.xml中加入shiro依赖 <!-- shiro --> <dependency> <groupId>org.apache.shi ...

  5. 在web项目中使用shiro(认证、授权)

    一.在web项目中实现认证 第一步,在web项目中导入shiro依赖的包 第二步,在web.xml中声明shiro拦截权限的过滤器 <filter> <filter-name> ...

  6. Shiro入门之一 -------- Shiro权限认证与授权

    一  将Shirojar包导入web项目 二 在web.xml中配置shiro代理过滤器 注意: 该过滤器需要配置在struts2过滤器之前 <!-- 配置Shiro的代理过滤器 -->  ...

  7. shiro权限认证与授权

    什么是shiro? Shiro是apache旗下一个开源框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权.加密.会话管理等功能,组成了一个通用的安全认证框架. 为什么要用sh ...

  8. SSM 整合 Shiro

    1. 导包 <!-- spring --> <dependency> <groupId>org.springframework</groupId> &l ...

  9. Shiro的认证与授权

    shiro实战教程 一.权限管理 1.1什么是权限管理 基本上涉及到用户参与的系统都需要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以 ...

随机推荐

  1. 状态压缩dp poj 3254 hdu5045

    近来感觉状态压缩dp的强大性(灵活利用了二进制运算非常关键). . . 于是做了俩提来看看..毕竟队友是专业的dp.我仅仅是管中窥豹下而已.. 日后有机会再与之玩耍玩耍...ps:假设上天再给我一次机 ...

  2. iOS关于iPhone6和iPhone6 Plus的屏幕适配问题

    iPhone6和iPhone6 Plus上市有一段时间了.尽管大陆没有首发令人隐隐作痛,可是还是为iPhone6和iPhone6 Plus的设计的转变和大屏时代感到欣喜. 今天主要来mark下面通过x ...

  3. Leetcode:remove_element

    一.     题目 给定一个数组和一个值.删除当中和给定值相等的元素.返回得到的新数组长度 二.     分析 刚開始我以为仅仅须要返回最后的数组长度即可了呢! 后来WA了一次才知道还得把心数组构造好 ...

  4. JS遮罩层

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  5. android 更新ui

    https://www.cnblogs.com/rayray/p/3437048.html https://www.cnblogs.com/zhaoyanjun/p/5546683.html

  6. Android下添加新的自定义键值和按键处理流程【转】

    本文转载自: Android下添加新的自定义键值和按键处理流程     说出来不怕大家笑话,我写这篇博客的原因在于前几天去一个小公司面试Android系统工程师,然后在面试的时候对方的技术总监问了我一 ...

  7. 第4章 部署模式 Three-Tiered Distribution(三级分布)

    影响因素 Tiered Distribution 中讨论的影响因素也适用于此模式.有关这些通用影响因素的讨论,请参阅"Tiered Distribution".下列影响因素仅适用于 ...

  8. 百度地图api的简单应用

    百度地图api 获取经纬度(通过浏览器的) //获取经纬度 window.navigator.geolocation.getCurrentPosition(function(position) { a ...

  9. JavaScript的continue和break的区别

    <html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...

  10. 算法 之 3n+1问题

    卡拉兹(Callatz)猜想: 对任何一个自然数n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把(3n+1)砍掉一半.这样一直反复砍下去,最后一定在某一步得到n=1.卡拉兹在1950年的世界数 ...