简介: Shiro 是一个 Apache Incubator 项目,旨在简化身份验证和授权。是一个很不错的安全框架。
下面记录一下shiro和Spring整合的过程的一个小示例:
Web.xml配置
<context-param>
<param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml,classpath:spring-shiro.xml</param-value>
</context-param>
<!-- apache 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>*.do</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
第一部分是将shiro的配置文件引入到web.xml中,我这里是spring-shiro.xml;
下面的是一个过滤器,过滤.do,.jsp的请求,引入shiro web.xml就配这么多。
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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<description>Shiro 配置</description>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login.jsp" />
<property name="successUrl" value="/login.jsp" />
<property name="unauthorizedUrl" value="/error/noperms.jsp" />
<property name="filterChainDefinitions">
<value>
/login.jsp* = anon
/login.do* = anon
/index.jsp*= anon
/error/noperms.jsp*= anon
/*.jsp* = authc
/*.do* = authc
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--设置自定义realm -->
<property name="realm" ref="monitorRealm" />
</bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!--自定义Realm 继承自AuthorizingRealm -->
<bean id="monitorRealm" class="com.springmvc.service.MonitorRealm"></bean>
<!-- securityManager -->
<bean
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod"
value="org.apache.shiro.SecurityUtils.setSecurityManager" />
<property name="arguments" ref="securityManager" />
</bean>
<!-- Enable Shiro Annotations for Spring-configured beans. Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
</beans>
这里不想说太多,我这里没什么特别的,很多都是用的shiro自己的原有的,只有一个realm是我自己定义的,可能自己定义的会更好用点吧,如果不用自己定义的就用shiro的jdbcrealm,我自定义的也是跟jdbcrealm差不多的,后面我们再说我的自定义realm。另外就是给页面指定过滤器
/login.jsp* = anon /login.do* = anon /index.jsp*= anon /error/noperms.jsp*= anon /*.jsp* = authc /*.do* = authc
Anon:不指定过滤器,不错是这个过滤器是空的,什么都没做,跟没有一样。
Authc:验证,这些页面必须验证后才能访问,也就是我们说的登录后才能访问。
这里还有其他的过滤器,我没用,比如说授权,这个比较重要,但是这个过滤器有个不好的地方,就是要带一个参数,所以如果配在这里就不是很合适,因为每个页面,或是.do的权限不一样,而我们也没法事先知道他需要什么权限。所以这里不配,我们在代码中再授权。这里.do和.jsp后面的*表示参数,比如login.jsp?main这种,是为了匹配这种。好行了,继续往下吧。
验证:
验证我们就弄一个登录页面,然后提交到后台的action
@RequestMapping(params = "main")
public ModelAndView login(User user,HttpSession session, HttpServletRequest request) {
ModelAndView modelView = new ModelAndView();
Subject currentUser = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(
user.getUsercode(), EncryptUtils.encryptMD5(user.getPassword()));
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (AuthenticationException e) {
modelView.addObject("message", "login errors");
modelView.setViewName("/login");
e.printStackTrace();
}
if(currentUser.isAuthenticated()){
session.setAttribute("userinfo", user);
modelView.setViewName("/main");
}else{
modelView.addObject("message", "login errors");
modelView.setViewName("/login");
}
return modelView;
}
这里我用的是spring MVC,你不用管他用什么mvc,我们只要知道,前台.do登录以后进入这个方法就行
Subject currentUser = SecurityUtils.getSubject()
;就是代表当前的用户。
UsernamePasswordToken token = new UsernamePasswordToken( user.getUsercode(),EncryptUtils.encryptMD5(user.getPassword()));
这里的token大家叫他令牌,也就相当于一张表格,你要去验证,你就得填个表,里面写好用户名密码,交给公安局的同志给你验证。
currentUser.login(token);
这句是提交申请,验证能不能通过,也就是交给公安局同志了。这里会回调reaml里的一个方法
protected AuthenticationInfo doGetAuthenticationInfo()
验证是否通过
if(currentUser.isAuthenticated())
通过则转到你的页面,不通过到login页面并返回错误信息。
现在我们看看我们的reaml类,这是一个自定义的realm,
@Service("monitorRealm")
public class MonitorRealm extends AuthorizingRealm {
/*
* @Autowired UserService userService;
*
* @Autowired RoleService roleService;
*
* @Autowired LoginLogService loginLogService;
*/
public MonitorRealm() {
super();
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
/* 这里编写授权代码 */
Set<String> roleNames = new HashSet<String>();
Set<String> permissions = new HashSet<String>();
roleNames.add("admin");
permissions.add("user.do?myjsp");
permissions.add("login.do?main");
permissions.add("login.do?logout");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
info.setStringPermissions(permissions);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
/* 这里编写认证代码 */
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
// User user = securityApplication.findby(upToken.getUsername());
User user = new User();
user.setUsercode(token.getUsername());
user.setUserName("admin");
user.setPassword(EncryptUtils.encryptMD5("admin"));
// if (user != null) {
return new SimpleAuthenticationInfo(user.getUserName(),
user.getPassword(), getName());
}
public void clearCachedAuthorizationInfo(String principal) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(
principal, getName());
clearCachedAuthorizationInfo(principals);
}
}
这里我没有跟数据库打交道,如果要跟数据库打交道很简单,你调用一个service,service再调dao,根据用户名去打该用户的密码。用户我们可以前面的令牌也就是我说的表格来取的,我们前台提交给公安同志一个表格,里面有用户密码,但需要注意的是,我们在这里并不把表格中的用户密码路数据库中的用户密码进行比较,我们只是根据表格中的用户名把密码查出来,然后把数据库的用户密码放在一个SimpleAuthenticationInfo对象中返回即可,这位公安同志不负责验证,只负责验证的材料。我这里没有查库,伪造了一个用户密码放入了对象。密码是admin。什么时候验证,就是我们前面调currentUser.isAuthenticated()时验证,所有的材料都全了,需要验证的时候就调一下这个方法就可以了。我们前面spring里配了这个
/*.jsp* = authc
/*.do* = authc
你配了authc过滤器,shiro会自动调currentUser.isAuthenticated()这个方法,没有登录的将被返回
<property name="unauthorizedUrl" value="/error/noperms.jsp" />
配置的页面。
好到这里登录就算是完成了。完成了登录下面就是要授权了,我们已经登录系统,我进入系统总要做点什么吧,比如这个系统就是一个公司的话,我现在已经进入公司了,如果我要进办公室,还得要授权(假如有门禁的话)刷卡。这们就里就是访问某个页面或是某个.do,
授权:
因为前面我们只配了验证过滤器,现在已经登录系统,如果我们请求一个*.do的话就会来到后台的action,我们授权也将在这里授。
Java代码
@Controller
@RequestMapping(value="user")
public class UserController {
/**
* 跳转到myjsp页面
*
* @return
*/
@RequestMapping(params = "myjsp")
public String home() {
Subject currentUser = SecurityUtils.getSubject();
if(currentUser.isPermitted("user.do?myjsp")){
return "/my";
}else{
return "error/noperms";
}
}
}
我一直都说action,其实spring mvc里不再是action了,叫controller,我们这里的home方法的访问路径是user.do?myjsp,也就是我们登录系统后请求一个这个方法user.do?myjsqp,转到home方法后,我要看他有没有权限访问此方法,我就用下面的代码
Subject currentUser = SecurityUtils.getSubject();
currentUser.isPermitted("user.do?myjsp");
首先得到当前的用户,再看此用户是否有权访问user.do?myjsp,参数就是权限,这里后台数据库就会有这么一个权限,权限表中的权限地址就是user.do?myjsp,例如我们一般的系统左边是一棵功能菜单树,树的结点会有一个url链接,这个链接就是在权限表中。当然可能前面还会一个http:\\什么的。反正这里也跟后台的权限表中的地址一致就行了,shiro他是如何授权的。一样的你调用currentUser.isPermitted("user.do?myjsp");此方法后会回调realm中的protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals)方法,这个reaml类是非常重要的。这个类上面已经给出了,我们看看他是如何授权的。因为我没有连数据库,也是伪造了一个权限。如果是连数据库也很简单,用户表,角色表,权限表这三个表是有关联的,我们根据用户名就能查出此用户拥有的角色和所有的权限。
Set<String> roleNames = new HashSet<String>();
Set<String> permissions = new HashSet<String>();
roleNames.add("admin");
permissions.add("user.do?myjsp");
permissions.add("login.do?main");
permissions.add("login.do?logout");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
info.setStringPermissions(permissions);
return info;
最后构造一个对象并把权限给它就OK拉。如果是数据库查出来的,直接我的字符串替成你查出来的就行了。这样在你的controller中根据权限返回到指定的页面。
if(currentUser.isPermitted("user.do?myjsp")){
return "/my";
}else{
return "error/noperms";
}
没有权限就返回到没有权限的页面。那么整个权限管理系统就算是差不多了,当然还有页面标签没说,这部分不是难点,自己找找资料吧,源码我整整一并奉上。。。。。。
分享到:
相关推荐
在这个"Shiro入门实例"中,我们将探讨Shiro的基础知识和如何在项目中进行实战应用。 **1. 认证与授权** Shiro 的核心概念包括主体(Subject)、安全管理者(SecurityManager)、身份验证(Authentication)、授权...
Apache Shiro 是一个强大的 Java 安全框架,专注于身份验证、授权和会话管理。它提供了简单易用的 API,使得开发者...本文提供的入门实例是一个基础的起点,实际使用时,你可能需要根据项目的具体需求进行扩展和定制。
Shiro入门实例 Shiro入门教程 Shiro框架学习demo http://www.xttblog.com/?p=669 权限管理教程。Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。 Shiro可以在任何环境下运行,小到最...
项目描述 SpringBoot整合Shiro,实现菜单权限控制入门简单实例;用户菜单权限来自数据库,简单起见,user用户表中同事配置了用户菜单权限,感兴趣的小伙伴可以...该入门实例为单体应用,资源文件位于resouces文件夹下
在这个"Shiro入门"压缩包中,包含了笔记和源码,是学习Shiro基础知识的好资源。 **一、Shiro基本概念** 1. **认证**:也称为身份验证,是确认用户身份的过程,通常通过用户名和密码进行验证。 2. **授权**:也称为...
- Security Manager处理验证结果,如果成功,创建Subject实例并绑定到当前线程。 4. **Shiro的授权机制** - 使用角色(Role)和权限(Permission)进行权限分配。 - Realm获取用户的角色和权限信息。 - Subject...
本教程将带你入门Shiro,并通过JDBC(Java Database Connectivity)连接数据库来实现用户身份验证。 首先,我们要了解Shiro的核心组件:SecurityManager、Realm、Subject和Session。SecurityManager是Shiro的顶层...
Shiro非常详细的实例,入门的详细资料
Shiro入门** Shiro的入门相对简单,首先需要在项目中引入Shiro的依赖。然后,你可以创建一个`SecurityManager`实例,这是Shiro的核心,负责管理所有安全相关的组件。接着,实现身份验证和授权逻辑,这通常涉及到...
接下来,我们看一个简单的Shiro入门示例代码。该示例首先通过IniSecurityManagerFactory读取classpath下的shiro.ini文件来初始化SecurityManager。之后通过SecurityUtils将SecurityManager实例绑定给SecurityUtils类...
文档"apache_shiro入门.docx"可能包含了Shiro的基本概念和用法介绍,例如Realm(认证和授权信息的数据源)、Subject(与当前安全操作相关的主体)、Session管理以及过滤器链的配置等内容。通过阅读这份文档,开发者...
### 三、Shiro入门 1. **配置Shiro**:首先,需要在项目中引入Shiro的依赖,然后配置Shiro的相关组件,如Realm(认证和授权的实现)。 2. **创建Subject**:Subject是Shiro的核心接口,代表当前操作的用户。可以...
Apache Shiro是一个全面的Java安全框架,它提供了身份验证、授权、加密以及会话管理等功能。Shiro框架在Java企业应用中广泛...通过本教程的入门程序,开发者可以快速掌握Shiro认证的基本流程,并将其应用到实际项目中。
接下来,可以通过创建一个 Guice Injector 并从中获取 SecurityManager 实例来使用这个模块: ```java Injector injector = Guice.createInjector(new MyShiroModule()); SecurityManager securityManager = ...
- **Shiro**是一个由Apache提供的开源安全(权限控制)框架,它具有简单且易于学习的特点,非常适合新手入门。 - **适用范围**:Shiro既适用于Java SE环境,也适用于Java EE环境。这意味着无论是在桌面应用程序还是...
在这个"shiro_ex源码"项目中,我们可以深入学习Shiro的基础知识和入门示例。下面将详细解释Shiro的核心概念、功能以及如何通过源码来理解和应用它们。 1. 认证(Authentication): Shiro 提供了用户身份验证的...
总的来说,"Shiro学习第一式身份验证1(HelloWorld)" 是一个入门级教程,旨在引导开发者初步接触 Shiro 框架,并掌握其基本的认证流程。通过实践这个示例,你将能够更好地理解 Shiro 如何在 Java 应用中处理用户...
2. **创建 Subject**:在代码中,我们创建 `Subject` 实例,它是 Shiro 中的核心概念,代表了当前的用户。通常,我们通过 `SecurityUtils.getSubject()` 获取它。 3. **登录**:接着,我们使用 `subject.login()` ...