场景:
本例实现用户/口令正常登入,并且实现@RequiresPermissions("sys:user:query")权限验证
1.本例环境
1>.本例源码下载地址: https://github.com/zhangbeizhen/spring-shiro
2>.本例环境 shiro + spring + mybatis + eclipse Mars + 基于maven的web项目
3.1>. spring集成mybatis的源码下载地址: https://github.com/zhangbeizhen/spring-mybatis
3.2>. spring集成mybatis参考博客地址: https://blog.csdn.net/zhangbeizhen18/article/details/88575287
2.本例说明
本例是在spring集成mybatis的基础上进行集成shiro,本例是本人学习过程中为了适合更好理解shiro改造的domo
参考了几个开源开源代码,感谢.
3.集成shiro配置文件分成3部分
3.1>在web.xml中配置
<!-- Apache Shiro start-->
<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>
<!-- Apache Shiro end-->
3.2>在spring-mvc.xml中配置
<!-- 支持Shiro对Controller的方法级AOP安全控制 2019-3-21 start -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true" />
</bean>
<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">error/403</prop>
<prop key="java.lang.Throwable">error/500</prop>
</props>
</property>
</bean>
<!-- 支持Shiro对Controller的方法级AOP安全控制 end -->
3.3>在spring-context-shiro.xml中配置
<!-- Shiro权限过滤过滤器定义 -->
<bean name="shiroFilterChainDefinitions" class="java.lang.String">
<constructor-arg>
<value>
/static/** = anon
/login = authc
/sys/login/**=anon
/logout = logout
/** = authc
</value>
</constructor-arg>
</bean>
<!-- 安全认证过滤器 shiroFilter-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="filterChainDefinitions">
<ref bean="shiroFilterChainDefinitions"/>
</property>
</bean>
<!-- 定义Shiro安全管理配置 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myShiroRealm" />
</bean>
<!-- 注入盐属性2019-3-21 -->
<bean id="myShiroRealm" class="com.zbz.realm.MyShiroRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 加密方式 -->
<property name="hashAlgorithmName" value="MD5" />
<!-- 加密次数 -->
<property name="hashIterations" value="3" />
<!-- 存储散列后的密码是否为16进制 -->
<!-- <property name="storedCredentialsHexEncoded" value="true" /> -->
</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- AOP式方法级权限检查 -->
<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>
4.集成shiro的java代码
4.1自定义类继承实现抽象类org.apache.shiro.realm.AuthorizingRealm两个方法
<1>.protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
此方法在登入时候调用进行登入认证,从数据库中获用户/口令等进行认证,认证成功后即登入了.
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
logger.info("权限认证开始......");
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
String username = usernamePasswordToken.getUsername();
UserService userService = SpringUtil.getBean(UserService.class);
User user = userService.getUser(username);
if (user == null) {
throw new UnknownAccountException("用户名不存在");
}
if (!user.getPassword()
.equals(userService.passwordEncoder(new String(usernamePasswordToken.getPassword()), user.getSalt()))) {
throw new IncorrectCredentialsException("密码错误");
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(),
ByteSource.Util.bytes(user.getSalt()), getName());
UserUtil.setUserSession(user);
logger.info("权限认证结束......");
return authenticationInfo;
}
<2>.protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
此方法在登入成功后,再次进行访问后调用,进行授权,是否可以访问某个特定方法。
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
logger.info("授权开始......");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
User user = UserUtil.getCurrentUser();
List<Role> roles = SpringUtil.getBean(RoleDao.class).listByUserId(user.getId());
Set<String> roleNames = new HashSet<String>();
if (roles != null && roles.size() > 0) {
for (int i = 0; i < roles.size(); i++) {
Role role = roles.get(i);
if (!StringUtils.isEmpty(role.getName())) {
roleNames.add(role.getName());
}
}
}
authorizationInfo.setRoles(roleNames);
List<Permission> permissionList = SpringUtil.getBean(PermissionDao.class).listByUserId(user.getId());
UserUtil.setPermissionSession(permissionList);
Set<String> permissions = new HashSet<String>();
if (permissionList != null && permissionList.size() > 0) {
for (int i = 0; i < permissionList.size(); i++) {
Permission permission = permissionList.get(i);
if (!StringUtils.isEmpty(permission.getPermission())) {
permissions.add(permission.getPermission());
}
}
}
authorizationInfo.setStringPermissions(permissions);
logger.info("授权结束......");
return authorizationInfo;
}
4.2登入代码,即调用起点
@GetMapping("/sys/login")
public void login(String username, String password) {
logger.info("登入开始....");
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
SecurityUtils.getSubject().login(usernamePasswordToken);
// 设置shiro的session过期时间
SecurityUtils.getSubject().getSession().setTimeout(30 * 60 * 60 * 1000);
logger.info("登入完成....");
}
4.3测试权限方法
本例测试是否有@RequiresPermissions("sys:user:query")权限,
其中sys:user:query是shiro内部可解析的字符串,同时在数据库权限表中有配置好
@GetMapping("/{id}")
@RequiresPermissions("sys:user:query")
public User user(@PathVariable Long id) {
logger.info("根据用户id获取用户开始");
User user = userDao.getById(id);
logger.info("根据用户id获取用户 结束");
return user;
}
5.本例共计5张表
sys_user用户表,sys_role角色表,sys_role_user用户与角色关系表,
sys_permission权限表,sys_role_permission角色与权限关系表
6.测试url
登入:
http://127.0.0.1:8080/spring-shiro/sys/login?username=admin&password=admin
测试权限:
http://127.0.0.1:8080/spring-shiro/users/1
以上,TKS.