前情提示:
1、我的数据库一共有4种用户类型表:student、school、company、admin,每张表都有属性role,以此让shiro获得用户角色。
2、因为shiro的用户权限是默认交集的,即一个接口配置多个用户角色的话就时必须时全部都满足这个角色才能访问。因此我进行了第四步配置。如果没有这个问题的话可以忽略第四步。
3、我实现的方法比较笨拙,仅供参考。有啥问题可以留言,共同进步哈。
一、新建一个对象User类
public class User {
private Integer id;
private String password;
private String role;
public void setId(Integer id) {
this.id = id;
}
public void setPassword(String password) {
this.password = password;
}
public void setRole(String role) {
this.role = role;
}
public void setUserSalt(String userSalt) {
this.userSalt = userSalt;
}
public Integer getId() {
return id;
}
public String getPassword() {
return password;
}
public String getRole() {
return role;
}
public String getUserSalt() {
return userSalt;
}
private String userSalt;
}
二、新建一个文件夹Config,在其中新建一个UserRealm.java文件
package com.example.config;
import com.example.pojo.*;
import com.example.service.AdminService;
import com.example.service.CompanyService;
import com.example.service.SchoolService;
import com.example.service.StudentService;
import org.apache.shiro.authc.Account;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.SimpleSession;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import java.util.HashSet;
import java.util.Set;
public class UserRealm extends AuthorizingRealm {
@Autowired
AdminService adminService;
@Autowired
CompanyService companyService;
@Autowired
SchoolService schoolService;
@Autowired
StudentService studentService;
//返回当前realm的一个自定义名称
public String getName() {
return "UserRealm";
}
/**
* 获取授权信息
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了==》》授权doGetAuthorizationInfo");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取到当前用户
User user = (User) principalCollection.getPrimaryPrincipal();
// //赋予用户角色
//Role role = adminService.findRoleByAccountName(account.getUsername());
Set<String> roleSet = new HashSet<String>();
roleSet.add(user.getRole());
info.setRoles(roleSet);
return info;
}
/**
* 认证
* <p>
* 获取认证的安全信息(从数据库查询用户的正确信息)
*
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了==》》doGetAuthenticationInfo");
//从token中获取用户名
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
String username = userToken.getUsername();
//用户名,密码,数据库中取
Admin admin = adminService.queryByUserName(Integer.valueOf(username));
Company company = companyService.queryByUserName(Integer.valueOf(username));
School school = schoolService.queryByUserName(Integer.valueOf(username));
Students st = studentService.queryByUserName(Integer.valueOf(username));
if (admin == null) {
if (company == null) {
if (school == null) {
if (st == null) {
return null;//用户名不存在
}
}
}
}
//获取session
Subject currentSubject = SecurityUtils.getSubject();
Session session = currentSubject.getSession();
User user=new User();
if (admin != null) {
session.setAttribute("loginUser", admin);
user.setId(admin.getId());
user.setPassword(admin.getPassword());
user.setRole(admin.getRole());
} else if (company != null) {
session.setAttribute("loginUser", company);
user.setId(company.getId());
user.setPassword(company.getPassword());
user.setRole(company.getRole());
} else if (school != null) {
session.setAttribute("loginUser", school);
user.setId(school.getId());
user.setPassword(school.getPassword());
user.setRole(school.getRole());
} else {
session.setAttribute("loginUser", st);
user.setId(st.getId());
user.setPassword(st.getPassword());
user.setRole(st.getRole());
}
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
三、在文件夹Config新建一个ShiroConfig.java文件
package com.example.config;
import org.apache.shiro.realm.jdbc.JdbcRealm;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
//ShiroFilterFactoryBean
//DafaultWebSecurityManager
//创建realm对象
//ShiroFilterFactoryBean
//过滤器
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
// ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// //设置安全管理器
// shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
// 存放自定义的filter
LinkedHashMap<String, Filter> filtersMap = new LinkedHashMap<>();
// 配置自定义 or角色 认证
filtersMap.put("roles", new MyShiroFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
// Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
/*
anon:无需认证可以访问
authc:必须认证才能访问
user:必须拥有 记住我 功能才能用
perms:拥有对某个资源的权限才能访问
role:拥有某个角色权限才能访问
*/
//登录拦截
Map<String, String> filterMap = new LinkedHashMap<>();
//用户进入登录界面,无需认证 登陆不拦截
filterMap.put("/admin/login", "anon");
filterMap.put("/student/login", "anon");
filterMap.put("/company/login", "anon");
filterMap.put("/school/login", "anon");
// filterMap.put("/**", "authc");
// //用户进入系统,必须进行登录验证
System.out.println(filterMap);
//角色拦截 我只展示部分的
//admin
filterMap.put("/admin/showAll", "authc,roles[admin]");
filterMap.put("/admin/showById", "authc,roles[admin]");
filterMap.put("/admin/fixPassword", "authc,roles[admin]");
//company
filterMap.put("/company/showAll", "authc,roles[admin,school,student]");
filterMap.put("/company/selectByAll", "authc,roles[admin,school,student]");
filterMap.put("/company/deleteById", "authc,roles[admin,school]");
filterMap.put("/company/add", "authc,roles[admin,school]");
filterMap.put("/company/showById", "authc,roles[company]");
filterMap.put("/company/fixPassword", "authc,roles[company]");
filterMap.put("/company/fixMessage", "authc,roles[company]");
//设置登出
//filterMap.put("/logout", "logout");
//设置admin下的某个方法需要某个权限
// filterMap.put("/sys/admin/find", "perms[admin:find]");
System.out.println(filterMap);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
// shiroFilterFactoryBean.setLoginUrl();
// //设置未授权访问的页面路径401(无权限界面)
// shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
return shiroFilterFactoryBean;
}
//DefaultWebSecurityManager:2
@Bean("defaultWebSecurityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("UserRealm")UserRealm userRealm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//关联userRealm
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
//自定义realm
@Bean("UserRealm")
public UserRealm getUserRealm() {
UserRealm userRealm=new UserRealm();
return userRealm;
}
}
四、在文件夹Config新建一个MyShiroFilter.java文件
package com.example.config;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.springframework.context.annotation.Configuration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@Configuration
public class MyShiroFilter extends AuthorizationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
Subject subject = getSubject(request, response);
String[] rolesArray = (String[]) mappedValue;
//没有角色限制,没有权限访问
if (rolesArray == null || rolesArray.length == 0) {
return false;
}
//若当前用户是rolesArray中的任何一个,则有权限访问
for (int i = 0; i < rolesArray.length; i++) {
if (subject.hasRole(rolesArray[i])) {
return true;
}
}
return false;
}
}
五、在每个登陆接口的service插入语句:
//shrio验证
Subject subject= SecurityUtils.getSubject();
UsernamePasswordToken token =new UsernamePasswordToken(String.valueOf(admin.getId()),admin.getPassword());
subject.login(token);
Over!!!亲测可用呀