1, 什么是Shiro?
Shiro是一个安全框架,用于解决系统的认证和授权问题,同时提供了会话管理,数据加密,与WEB集成,缓存等机制。
Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
2、传统认证与Shiro的对比。
传统的认证,在controller层,自己编写相应的业务层与doa层方法获取数据库存储的数据进行验证
shiro、需要在shiro的realm中配置好,保存真实的数据源的地址,以及验证的方式( ....)。在controller与shiro进行交互
3,Shiro的架构
Subject:主体,可以看到主体可以是任何可以与应用交互的“用户”; 这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫等;即一个抽象概念;
SecurityManager:Shiro的核心控制器,相当于SpringMVC中的DispatcherServlet;所有具体的交互都通过SecurityManager进行控制;它管理着所有Subject、且负责进行认证和授权、及会话、缓存的管理。
Authenticator:认证器,负责主体认证。
Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;
Realm:域,Shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
SessionManager:管理Session生命周期的组件;Shiro并不仅可以用在Web环境,也可以用在如普通的JavaSE环境、EJB等环境;因此Shiro抽象了一个SessionManager来管理主体与应用之间交互的数据;
SessionDAO:用来将Session保存到数据库,可以实现自己的SessionDAO,通过如JDBC写到数据库;或者把Session放到Memcached中,可以实现自己的Memcached SessionDAO;另外SessionDAO中可以使用Cache进行缓存,以提高性能;
CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能
Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密的。
4,Shiro与应用程序的交互过程
1)应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;
2)我们需要给Shiro的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及其权限进行判断。
5,shiro认证
6. Shiro授权:
授权,也叫访问控制,即在应用中控制谁能访问哪些资源
7.Shiro加密
Shior散列HashedCredentialsMatcher密码匹配器
自定义Realm中使用盐值加密
8.Web集成:
a) Shiro提供了与Web集成的支持,其通过一个ShiroFilter
入口来拦截需要安全控制的URL,ShiroFilter类似于如Strut2/SpringMVC这种web框架的前端控制器,是安全控制的入口点,负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作
b) org.springfraemwork.web.filter.DelegatingFilterProxy
rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。
port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString
是你访问的url里的?后面的参数。
perms:例子/admins/user/**=perms[user:add:*],perms参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于
isPermitedAll()方法。
roles:例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如/admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。
anon:例子/admins/**=anon 没有参数,表示可以匿名使用。
authc:例如/admins/user/**=authc表示需要认证才能使用,没有参数
authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证
ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https
user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查
其中anon,authcBasic,auchc,user是是认证过滤器,perms,roles,ssl,rest,port授权过滤器。
9.集成spring
A,配置过滤器,在webapp.xml中
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
B,spring配置,参照shiro第二斩
<!--shiro配置--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="loginUrl" value="login.html"></property> <property name="securityManager" ref="securityManager"></property> <property name="unauthorizedUrl" value="403.html"></property> <property name="successUrl" value="index"></property> <property name="filterChainDefinitions"> <value> /login.html = anon /doLogin = anon /* = authc </value> </property> </bean>
springboot配置。这个是自定义域。SSM与springboot一样的。注册的方式不同。这个要加入到securityManager中
public class CustomRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private FunctionService functionService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("授权"); User user = (User)principalCollection.getPrimaryPrincipal(); //从数据中获取角色权限数据 User roleUser = userService.findUserRolePremissionsByUserCode(user.getUsercode()); List<String> premissions = new ArrayList<>(); List<String> roles = new ArrayList<>(); roles.add(roleUser.getRole().getRolename()); for(Function f :roleUser.getRole().getFunctions()){ premissions.add(f.getFunctionname()); } // List<String> list = functionService.getFunctionNameByUserCode(user.getUsercode()); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermissions(premissions);//权限 info.addRoles(roles);//角色 return info; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //从主体提交过来的认证信息中 String userName = (String)authenticationToken.getPrincipal(); //通过用户名到数据库中获取凭证 User user = userService.getUserByName(userName); System.out.println(userName+"??"); if(user == null){ return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getUserpassword(),this.getName()); info.setCredentialsSalt(ByteSource.Util.bytes("hello")); return info; }
10.shiro标签
10.Shiro权限注解
Shiro提供了相应的注解用于权限控制,如果使用这些注解就需要使用AOP的功能来进行判断,Shiro提供了Spring AOP集成用于权限注解的解析和验证。
1) 在spring-mvc.xml配置文件添加Shiro Spring AOP权限注解的支持:
<aop:config proxy-target-class="true"></aop:config> <bean class=" org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean>
2) 配置依赖:
<dependency> <groupId>aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.0</version> </dependency>
3) 当验证失败,其会抛出UnauthorizedException异常,此时可以使用Spring的ExceptionHandler(DefaultExceptionHandler)来进行拦截处理:
@ExceptionHandler({UnauthorizedException.class}) public ModelAndView processUnauthenticatedException() { ModelAndView mv = new ModelAndView(); mv.setViewName("forward:/403.html"); return mv; }
4)注解
@RequiresAuthentication 表示当前Subject已经通过login进行了身份验证;即Subject. isAuthenticated()返回true。
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
表示当前Subject需要角色admin和user。
@RequiresPermissions (value={“user:update”, “user:delete”}, logical= Logical.OR)
表示当前Subject需要权限user:update或user:delete
SpringBoot集成Shiro
一. 配置依赖
二. Shiro配置
三. thymeleaf使用shiro
- 1. 配置依赖
- A. <dependency>
- B. <groupId>com.github.theborakompanioni</groupId>
- C. <artifactId>thymeleaf-extras-shiro</artifactId>
- D. <version>2.0.0</version>
- E. </dependency>
- 2. 注册Bean
- A. ShiroDialect
- 3. xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"