shiro登录授权框架
- Shiro四大基石(身份认证,授权,会话管理,密码学)
- shiro核心对象:SecurityManager对象
- 控制层登录认证:获取到SecurityManager对象后,通过SecurityUtils将SecurityManager设置到shiro环境中去和获取主体,然后在创建一个令牌,主体登录,将token传入进去。
@RequestMapping("/login")
public String login(String username,String password){
// 获取当前登录的主体
Subject subject = SecurityUtils.getSubject();
// 判断当前主体是否已经通过了验证
if (!subject.isAuthenticated()){
// 没有通过验证,获取token传入username和password进行登录
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try {
subject.login(token);
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户名不存在");
}catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码错误");
}catch (AuthenticationException e) {
e.printStackTrace();
System.out.println("未知错误");
}
}
return "redirect:/s/main.jsp";//跳转到登录成功的页面去
} - 自定义realm(继承AuthorizingRealm)
认证,授权,加密 - Shiro整合Spring
a) 导入shiro和Spring的整合包
<!-- shiro的支持包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.4.0</version>
<type>pom</type>
</dependency>
<!-- shiro与Spring的集成包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
b) 在web.xml配置shiroFilter(代理过滤器)
<!--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>
c) 配置Shiro的配置文件:配置shiro安全管理器,和自定义的realm,配置让shiro支持注解,配置真实过滤器(Id必须与web.xml 中的shiroFilter名字对应),真实过滤器中要配置放行和拦截,然后在Spring配置文件中引入shiro的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--shiro核心安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<!--自定义的realm-->
<bean id="myRealm" class="cn.itsource.aisell.shiro.MyRealm">
<!--配置加密方式
加盐的话就在myRealm实体类在返回SimpleAuthenticationInfo之前加盐。
-->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"/>
<property name="hashIterations" value="10"/>
</bean>
</property>
</bean>
<!--配置支持shiro注解-->
<!-- 3.lifecycleBeanPostProcessor:可以自动调用在Spring Ioc窗口中 Shiro bean的生成周期方法 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 4.启动ioc容器中使用 shiro的注解,但是必需配置在Spring Ioc容器中Shiro bean的生成周期方法 -->
<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>
<!--配置shiro的真实过滤器-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<!--登录界面-->
<property name="loginUrl" value="/s/login.jsp"/>
<!--登录成功界面-->
<property name="successUrl" value="/s/main.jsp"/>
<!--登录成功没有全县的界面-->
<property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
<!--
配置哪些资源被保护,哪些资源需要权限
anon:不需要登录也可以访问相应的权限
authc:需要权限才能访问
/** :所有文件及其子文件,这里笔者创建了一个bean来装权限交给Spring进行管理
-->
<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap">
<!--<value>-->
<!--<!–anon放行,authc拦截–>-->
<!--/login = anon-->
<!--/s/login.jsp = anon-->
<!--<!–对资源进行权限控制,要控制的资源都应该从数据库查出,现在咱们先写死–>-->
<!--/s/permission.jsp = perms[user:*]-->
<!--/** = authc-->
<!--</value>-->
</property>
</bean>
<bean id="filterChainDefinitionMap" factory-bean="aisellFilterChainDefinitionMapBuilder" factory-method="creatFilterChainDefinitionMap"/>
<bean id="aisellFilterChainDefinitionMapBuilder" class="cn.itsource.aisell.shiro.AisellFilterChainDefinitionMapBuilder"/>
</beans>
- shiro的两大核心(登录验证和授权)
a) 登录验证
i. 在控制层前台传过来两个登录信息,首先通过SecurityUtils获取到当前登录的主体,判断这个主体是否已经通过了验证,如果没有通过验证,就new UsernamePasswordToken对象传入前 台传入的两个登录信息,然后主体调用登录方法,进行登录。在自定义的Realm(我这里是myRealm),进行登录验证,通过赋写的方法的参数获取到当前主体,获取到登录的两个信息,然后到 数据库查询是否有这个信息,有就登录成功,没有就登陆失败,向前台返回一个 SimpleAuthenticationInfo对象
// 身份认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取当前主体
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername();
String password = findPasswordByUsername(username);
if (password==null){
return null;
}
// SimpleHash simpleHash = new SimpleHash("MD5", "147258", 10);
// System.out.println(simpleHash);
// 填加盐值
ByteSource salt = ByteSource.Util.bytes("itsource");
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getName());
return authenticationInfo;
}
private String findPasswordByUsername(String username){
if ("admin".equals(username)){
// 这个是进行了加密的密码
return "d824670230ca2856ad808c0c0f834b42";
}
return null;
}
b) 授权
i. 首先我们定义一个实体类,来创建map集合来存储权限交给Spring管理,然后在Spring的配置文件里面配置这个bean。在外面自定义的realm(我的是MyRealm)中进行一个授权,首先通 过赋写的方法的参数获取带当前的登录对象,定义一个Set来装权限,通过获取SimpleAuthorizationInfo对象将Set穿进去与Spring管理的Map权限进行比对
// 身份授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
// 获取当前登录主体
String username = (String)principals.getPrimaryPrincipal();
System.out.println("后面需要根据用户名获取资源"+username);
// 定义一个set来装权限
HashSet<String> permissons = new HashSet<>();
// 添加权限
permissons.add("user:*");
// 将权限交给Spring进行比对
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 将权限交给设置进去Spring
authorizationInfo.setStringPermissions(permissons);
return authorizationInfo;
}
- Shiro的密码学
a)
我们先在我们xml配置的自定义的realm里面添加加密的方式,注意这里面只能添加密的方式和次数,如果要添加盐值的话就要到MyRealm的实体类中的身份认证方法里面去添加盐值
在上面的shiro配置文件里面有配置