编辑器要配置好spring的插件。具体可以百度
首先配置spring的环境
web.xml下
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
此处是spring的配置
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
此处是springmvc的配置
<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>
此处是shiro的配置 !此处要等spring配置好之后再加入!
创建
applicationContext.xml 创建在src根目录下
用于做spring的配置
创建spring-servlet.xml 创建在web-inf下
<context:component-scan base-package="com.test.shiro"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler/>
这里是做springmvc用的 前端控制器 扫描的包
新建这个路径
com.test.shiro
新建jsp文件 user.jsp
运行项目:http://localhost:8080/shiro/user.jsp
打开出现user.jsp正常说明SPRING的环境已经配置好了
------
------
接下来开始整合shiro
web.xml文件已经加入了
在applicationContex.xml(也就是SPING来管理的shiro)中写入
核心部分 权限管理 SecurityManager
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="cacheManager"/> 缓存
------ 这里是整合后才需要的 先注释 不然报错
<property name="authenticator" ref="authenticator"></property> <property name="realms"> <list> <ref bean="jdbcRealm"/> <ref bean="secondRealm"/> </list> </property> <property name="rememberMeManager.cookie.maxAge" value="10"></property>
------ 这里是整合后才需要的 先注释 不然报错
现在需要的配置是 :全部整合好了之后可以不用 <property name="realm" ref="jdbcRealm"></property>
</bean>
1.配置缓存cacheManager
cacheManager采用企业的管理方式 使用ehcache 。这个是需要加入jar包的 还有一种直接引用ehcachemanager
然后配置XML文件后期才再给。直接拿来使用就行。
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- Set a net.sf.ehcache.CacheManager instance here if you already have one. If not, a new one
will be creaed with a default config:
<property name="cacheManager" ref="ehCacheManager"/> -->
<!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance to inject, but you want
a specific Ehcache configuration to be used, specify that here. If you don't, a default
will be used.: -->
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean>
2.可以配置session 现在展示不用
3.实现realm
用接口的方式实现
<bean id="jdbcRealm" class="com.test.shiro.realms.ShiroRealm">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"></property>
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean>
java文件:
4.配置生命周期shiro
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
5.ioc容器可以使用shiro的注解(配置了4之后才会出现效果)
<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>
6.配置shirofiter 这里和web.xml中是是对应的。
<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="/list.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
------ 这里是整合后才需要的 先注释 不然报错
<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property> 后期加上比较好的配置
------ 这里是整合后才需要的 先注释 不然报错
<!-- 配置哪些页面需要受保护. 以及访问这些页面需要的权限.
1). anon 可以被匿名访问
2). authc 必须认证(即登录)后才可能访问的页面.
3). logout 登出.
4). roles 角色过滤器 -->
<property name="filterChainDefinitions">
<value> /login.jsp = anon
/shiro/login = anon
/shiro/logout = logout
/user.jsp = roles[user]
/admin.jsp = roles[admin]
# everything else requires authentication:
/** = authc </value> </property>
</bean>
-----运行。此时框架已经可以跑起来 下载地址:http://download.csdn.net/detail/u013354696/9864885
下面进行整合realm实现认证
/shiro/src/com/test/shiro/handler/ShiroHandler.java 新建控制器
大致的作用就是将表单接收到的用户密码封装起来。进行登录验证
记得要加上控制器的注解
@Controller @RequestMapping("/shiro") public class ShiroHandler { @RequestMapping("/login") public String login(@RequestParam("username") String username, @RequestParam("password") String password) { Subject subject = SecurityUtils.getSubject(); if (!subject.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken(username, password); token.setRememberMe(true); try { subject.login(token); } catch (AuthenticationException e) { System.out.println("登录失败" + e.getMessage()); } } return "redirect:/list.jsp"; } }
/shiro/src/com/test/shiro/realms/ShiroRealm.java 这个继承类之前就已经创建好。但是不用实现realm接口要改为继承AuthenticatingRealm
public class ShiroRealm extends AuthenticatingRealm { @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { System.out.println("doGetAuthenticationInfo"+token); return null; } }
到此,可以运行项目会发现地址栏目的改变:
http://localhost:8080/shiro/login.jsp;jsessionid=BB3ACC73995EC9EE6AFB0FEC74DAC2D1
后面读了一个jsessionid的参数
输入了登录密码信息后,控制台会打印出
doGetAuthenticationInfo:org.apache.shiro.authc.UsernamePasswordToken - 456, rememberMe=true
登录失败Realm [com.test.shiro.realms.ShiroRealm@7c1e7] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - 456, rememberMe=true].
证明执行成功
接下来在次改写/shiro/src/com/test/shiro/realms/ShiroRealm.java
@Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 1将AuthenticationToken转为usernamepasswordtoken UsernamePasswordToken upToken = (UsernamePasswordToken) token; // 2获取usernamepasswordtoken 中的username String username = upToken.getUsername(); // 3从数据库查询username的记录 if ("unknown".equals(username)) { throw new UnknownAccountException("用户不存在"); } //用户 密码 当前realm 直接用getName() SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, "123456", getName()); return info; }
其实就是做认证。用户名没有限定。密码123456 成功等会会进入跳转页面list.jsp
当然 也可以用AuthenticationToken 直接token.getPrincipal();强转一下获取当前用户信息这样就不需要 UsernamePasswordToken
开启加密MD5算法
web.xml里面的realm 改成这样
<bean id="jdbcRealm" class="com.test.shiro.realms.ShiroRealm"> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="MD5"></property> <property name="hashIterations" value="1024"></property> </bean> </property> </bean>
public static void main(String[] args) { Object re =new SimpleHash("MD5","123456" , null,1024); System.out.println(re); }
生成一个用MD5加密1024次 没有盐值的123456密码。
然后在替换到SimpleAuthenticationInfo 中的密码。就相当于这里已经执行了加密的算法
这里是最简单的实现
接下来是完整版本的实现
@Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 1将AuthenticationToken转为usernamepasswordtoken UsernamePasswordToken upToken = (UsernamePasswordToken) token; // // 2获取usernamepasswordtoken 中的username String username = upToken.getUsername(); String mima = null; // String username = (String) token.getPrincipal(); System.out.println("登录用户:" + username); // 3从数据库查询username的记录 if ("unknown".equals(username)) { throw new UnknownAccountException("用户不存在"); } if ("admin".equals(username)) { mima = "038bdaf98f2037b31f1e75b5b4c9b26e"; } else if ("user".equals(username)) { mima = "098d2c478e9c11555ce2823231e02ec1"; } ByteSource yan = ByteSource.Util.bytes(username); // 用户 密码 盐值 当前realm 直接用getName() SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, mima, yan, getName()); return info; }
----
以上完成了基本的加密和认证 还没有接入数据库的服务。全部都是静态的数据
----
接下来进行多realm的认证
场景的认证: 多个数据库源进行认证。需要多个realm实现不同的认证策略,比如密码的加密方式SHA1, MD5加密
/shiro/src/com/test/shiro/realms/SencondRealm.java
@Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 1将AuthenticationToken转为usernamepasswordtoken UsernamePasswordToken upToken = (UsernamePasswordToken) token; // // 2获取usernamepasswordtoken 中的username String username = upToken.getUsername(); String mima = null; // String username = (String) token.getPrincipal(); System.out.println("登录用户:" + username); // 3从数据库查询username的记录 if ("unknown".equals(username)) { throw new UnknownAccountException("用户不存在"); } if ("admin".equals(username)) { mima = "ce2f6417c7e1d32c1d81a797ee0b499f87c5de06"; } else if ("user".equals(username)) { mima = "073d4c3ae812935f23cb3f2a71943f49e082a718"; } ByteSource yan = ByteSource.Util.bytes(username); // 用户 密码 盐值 当前realm 直接用getName() SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, mima, yan, getName()); return info; } public static void main(String[] args) { Object re = new SimpleHash("SHA1", "123456", ByteSource.Util.bytes("user"), 1024); System.out.println(re); }
两个realm几乎是一样的,
在spring中配置realm
/shiro/src/applicationContext.xml加入
<bean id="secondRealm" class="com.test.shiro.realms.SencondRealm"> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="SHA1"></property> <property name="hashIterations" value="1024"></property> </bean> </property> </bean>
securityManager中的
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="cacheManager" ref="cacheManager"/> <property name="authenticator" ref="authenticator"></property> <property name="realms"> <list> <ref bean="jdbcRealm"/> <ref bean="secondRealm"/> </list> </property> <!-- <property name="rememberMeManager.cookie.maxAge" value="10"></property> --> </bean>
改为这个样子实现多realm
在配置一个认证器 具体可以去百度认证器策略。这里是所有的realm都认证
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean> </property> </bean>
也可以这样写 具体的策略可以自己决定
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"> <!-- <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean> </property> --> <property name="realms"> <list> <ref bean="jdbcRealm"/> <ref bean="secondRealm"/> </list> </property> <property name="authenticationStrategy"> <bean class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"></bean> </property> </bean>
项目跑起来可以自己进行测试了
刚刚以上是登录方面的,现在到配置权限
/shiro/src/com/test/shiro/realms/ShiroRealm.java 中的继承类改为 AuthorizingRealm 在实现方法
doGetAuthorizationInfo方法就是实现授权的方法
@Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection Principals) { //1. 从PrincipalCollection 拿到用户的信息 Object username = Principals.getPrimaryPrincipal(); //2. 拿到登录信息,去获取角色(查询数据库) Set<String> roles =new HashSet<>(); roles.add("user"); if("admin".equals(username)){ roles.add("admin"); } //3.都要实现这个接口返回值 SimpleAuthorizationInfo info =new SimpleAuthorizationInfo(roles); return info; }
完成页面
实现注解: 如果出错。权限限制都失效。把这个放到spring-mvc.xml中
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean>
进行测试。可以发现admin才可以获取到时间
-------
接下来可以将配置权限提取出来
appxxxx.xml
<bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapBuilder" factory-method="buildFilterChainDefinitionMap"></bean> <bean id="filterChainDefinitionMapBuilder" class="com.test.shiro.factory.FilterChainDefinitionMapBuilder"></bean>
shiroFilter中加入
<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property>
创建一个class
/shiro/src/com/test/shiro/factory/FilterChainDefinitionMapBuilder.java
public LinkedHashMap<String, String> buildFilterChainDefinitionMap() { LinkedHashMap<String, String> map =new LinkedHashMap<>(); map.put("/login.jsp", "anon"); map.put("/shiro/login", "anon"); map.put("/shiro/logout", "logout"); map.put("/user.jsp", "authc,roles[user]"); map.put("/admin.jsp", "authc,roles[admin]"); map.put("/list.jsp", "user"); map.put("/**", "authc"); return map;