shiro权限框架
1.shiro依赖包
<!-- 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>
</dependencies>
2.在web.xml中配置shiro代理过滤器
<!-- Spring与shiro集成:需要定义一个shiro过滤器(这是一个代理过滤器,它会到spring的配置中找一个名称相同的真实过滤器) -->
<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>
3.spring配置
<?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">
<!--配置安全管理者-->
<bean class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" id="securityManager">
<!--配置安全管理者的权限数据-->
<property name="realm" ref="myRealm"/>
</bean>
<bean class="com.wal.aisell.shiro.MyRealm" id="myRealm">
//设置密码的匹配方式
<property name="credentialsMatcher">
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--设置加密方式-->
<property name="hashAlgorithmName" value="MD5"/>
<property name="hashIterations" value="10"/>
</bean>
</property>
</bean>
<!--配置shiro生命周期方法-->
<bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor" id="lifecycleBeanPostProcessor"/>
<!--配置使用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过滤器 必须与web.xml中的代理过滤器名字一致-->
<bean class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" id="shiroFilter">
<property name="securityManager" ref="securityManager"/>
<!--登录时的url,如果没有登录会自动跳到该页面-->
<property name="loginUrl" value="/login"/>
<!--登录成功后跳到的页面-->
<property name="successUrl" value="/main"/>
<!--没有权限是跳到这个页面-->
<property name="unauthorizedUrl" value="/s/unauthorized.jsp"/>
<!--配置哪些资源被保护,哪些资源需要权限
anon:不需要登录也可以访问相应的权限
authc:需要权限才能访问
** :所有文件及其子文件
-->
<!--<property name="filterChainDefinitions">
<value>
/s/login.jsp=anon
/login=anon
/s/main.jsp=perms[user:*]
\/**=authc
</value>
</property>-->
<!--资源权限map-->
<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"/>
<!--引入自定义权限过滤器-->
<property name="filters">
<map>
<entry value-ref="myPermissionAuthorizationFilter" key="wal"></entry>
</map>
</property>
</bean>
<!--引入自定义权限过滤器bean-->
<bean class="com.wal.aisell.shiro.MyPermissionAuthorizationFilter" id="myPermissionAuthorizationFilter"/>
<!--在bean中设置哪些资源需要放行,哪些资源需要权限-->
<bean class="com.wal.aisell.shiro.FilterChainDefinitionMapBuilder" id="filterChainDefinitionMapBuilder"></bean>
<bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapBuilder"
factory-method="creatFilterChainDefinitionMap"/>
</beans>
资源权限MapfilterChainDefinitionMapBuilder
public class FilterChainDefinitionMapBuilder {
@Autowired
private IPermissionService permissionService;
public Map<String,String> creatFilterChainDefinitionMap(){
LinkedHashMap<String, String> map = new LinkedHashMap<>();
/* /s/login.jsp=anon
/login=anon
/s/main.jsp=perms[user:*]
*//**=authc*/
//静态资源放行
map.put("/login","anon");
map.put("*.js","anon");
map.put("*.css","anon");
map.put("/css/**","anon");
map.put("/js/**","anon");
map.put("/easyui/**","anon");
map.put("/images/**","anon");
//从数据库中读出访问路径所需要的权限
List<Permission> permissionList = permissionService.findAll();
permissionList.forEach(permission -> {
String url = permission.getUrl();
String sn = permission.getSn();
//这里要改成自定义的权限过滤器对应的key值
map.put(url, "wal["+sn+"]");
});
map.put("//**","authc" );
return map;
}
}
自定义权限过滤器 根据用户权限做相应处理
//复写默认权限过滤器,使其支持ajax请求
public class MyPermissionAuthorizationFilter extends PermissionsAuthorizationFilter {
//这是请求没有权限时处理的方法,默认是跳转页面,现在要加一个对ajax的处理
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
Subject subject = this.getSubject(request, response);
if (subject.getPrincipal() == null) {
this.saveRequestAndRedirectToLogin(request, response);
} else {
//先强转成http请求,因为http请求才能获得请求头
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
String header = req.getHeader("X-Requested-With");
//ajax请求的标志XMLHttpRequest
if (header != null && "XMLHttpRequest".equals(header)){
//设置响应类型
resp.setContentType("text/json,charset=UTF-8");
//设置响应消息
resp.getWriter().print("{\"seccess\":false,\"msg\":\"没有权限\"}");
}else {
String unauthorizedUrl = this.getUnauthorizedUrl();
if (StringUtils.hasText(unauthorizedUrl)) {
WebUtils.issueRedirect(request, response, unauthorizedUrl);
} else {
WebUtils.toHttp(response).sendError(401);
}
}
}
return false;
}
}
自定义MyRealm 用户身份认证和权限管理
public class MyRealm extends AuthorizingRealm {
//验证角色和权限
@Autowired
private IPermissionService permissionService;
@Autowired
private IRoleService roleService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//拿到身份验证成功后返回的主题
Employee employee = (Employee)principalCollection.getPrimaryPrincipal();
//更具登录用户得到该用户的角色信息
Set<Role> roles = roleService.findRolesByLoginUser(employee);
Set<String> rolesStr = new HashSet<>();
Set<String> permissionAll = new HashSet<>();
roles.forEach(role -> {
//根据登录用户的角色信息,拿到用户权限
Set<String> permission = permissionService.findPermissionByRole(role);
permissionAll.addAll(permission);
String sn = role.getSn();
rolesStr.add(sn);
});
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setStringPermissions(permissionAll);
authorizationInfo.setRoles(rolesStr);
//Set<String> permission = permissionService.findPermissionByLoginUser(employee);
//SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//authorizationInfo.setStringPermissions(permission);
return authorizationInfo;
}
//验证身份
@Autowired
private IEmployeeService employeeService;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//authenticationToken对应subject.login(token) 中的token
String username = (String)authenticationToken.getPrincipal();
String password = employeeService.findPasswordByusername(username);
Employee employee = employeeService.findByusername(username);
if (password==null){
return null;
}
//设置盐值
ByteSource salt = ByteSource.Util.bytes(MD5Utils.SALT);
//密码匹配成功后 ,subject.getPrincipal获得的就是employee,如果你写的是usernamesubject获得的就是username
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(employee, password,salt, getName());
return authenticationInfo ;
}