上一章:https://blog.csdn.net/qq_41780372/article/details/104823854
一、修改生成的實體,創建查詢用戶信息的方法
1.一個用戶是對應多個角色,一個角色對應多個權限(菜單)。
我們在用戶實體上面新增一個角色集合 SysUser.java
List<SysRole> roles;
在角色上面增加權限集合 SysRole.java
List<SysMenu> sysMenus;
記得兩個屬性上面均需要加上註解@TableField(exist = false),否則在查詢數據庫時mybaits-plus會把這個當做一個數據庫字段進行查詢。
2.新增加一個登陸的service,創建一個根據用戶名查用戶及所有角色和權限的方法。
SysLoginService.java內增加一個接口
SysUser getUserByName(String username);
SysLoginServiceImpl.java內實現接口
@Service
public class SysLoginServiceImpl implements SysLoginService {
@Autowired
private SysUserServiceImpl sysUserService;
@Autowired
private SysRoleServiceImpl sysRoleService;
@Autowired
private SysRoleMenuServiceImpl sysRoleMenuService;
@Autowired
private SysMenuServiceImpl sysMenuService;
@Autowired
private SysUserRoleServiceImpl sysUserRoleService;
@Override
public SysUser getUserByName(String username) {
SysUser sysUser=sysUserService.getOne(new QueryWrapper<SysUser>().eq("username",username));
if(sysUser!=null){
List<SysUserRole> sysUserRoles=sysUserRoleService.list(new QueryWrapper<SysUserRole>().eq("user_id",sysUser.getUserId()));
List<SysRole> sysRoles=new ArrayList<>();
for(SysUserRole sysUserRole:sysUserRoles){
SysRole sysRole=sysRoleService.getById(sysUserRole.getRoleId());
List<SysMenu> sysMenuList=new ArrayList<>();
List<SysRoleMenu> roleMenuList=sysRoleMenuService.list(new QueryWrapper<SysRoleMenu>().eq("role_id",sysUserRole.getRoleId()));
for(SysRoleMenu sysRoleMenu:roleMenuList){
sysMenuList.add(sysMenuService.getById(sysRoleMenu.getMenuId()));
}
sysRole.setSysMenus(sysMenuList);
sysRoles.add(sysRole);
}
sysUser.setRoles(sysRoles);
}
return sysUser;
}
}
二、編輯shiro的配置。
編輯CustomRealm.java
package cn.mvapi.xiaobao.common.shiro;
import cn.mvapi.xiaobao.common.system.entity.SysMenu;
import cn.mvapi.xiaobao.common.system.entity.SysRole;
import cn.mvapi.xiaobao.common.system.entity.SysUser;
import cn.mvapi.xiaobao.common.system.service.SysUserService;
import cn.mvapi.xiaobao.common.system.service.impl.SysLoginServiceImpl;
import cn.mvapi.xiaobao.common.system.service.impl.SysUserServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.springframework.beans.factory.annotation.Autowired;
public class CustomRealm extends AuthorizingRealm {
@Autowired
private SysLoginServiceImpl sysLoginService;
@Autowired
private SysUserServiceImpl sysUserService;
//進入角色授權 該方法是將用戶的角色及權限全部查出來
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//獲取登錄用戶名
String username = (String) principalCollection.getPrimaryPrincipal();
//根據用戶名去數據庫查詢用戶信息
SysUser sysUser = sysLoginService.getUserByName(username);//new QueryWrapper<SysUser>().eq("username",username));
//添加角色和權限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (SysRole role : sysUser.getRoles()) {
//添加角色
simpleAuthorizationInfo.addRole(role.getRoleName());
//添加權限
for (SysMenu sysMenu : role.getSysMenus()) {
if(sysMenu.getPerms()!=null&&!sysMenu.getPerms().trim().equals("")){
for(String str:sysMenu.getPerms().split(",")){
simpleAuthorizationInfo.addStringPermission(str);
}
}
}
}
return simpleAuthorizationInfo;
}
//主要用於賬號密碼校驗,通過用戶名查出數據庫內的密碼,交給shiro校驗
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//加這一步的目的是在Post請求的時候會先進認證,然後在到請求
if (authenticationToken.getPrincipal() == null) {
return null;
}
//獲取用戶信息
String name = authenticationToken.getPrincipal().toString();
SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>().eq("username",name));
if (user == null) {
//這裏返回後會報出對應異常
return null;
} else {
//這裏驗證authenticationToken和simpleAuthenticationInfo的信息
//用戶名–此處傳的是用戶對象
//密碼—從數據庫中獲取的密碼
//getName() //當前的realm名
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
return simpleAuthenticationInfo;
}
}
}
shiro配置 ShiroConfig.java
將上面的自定義realm添加到容器內,另外如果有多種校驗方式可以添加多個realm。
配置攔截的路徑和跳轉條件。
package cn.mvapi.xiaobao.common.shiro;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
//不加這個註解不生效,具體不詳
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
//將自己的驗證方式加入容器
@Bean
public CustomRealm myShiroRealm() {
CustomRealm customRealm = new CustomRealm();
return customRealm;
}
//權限管理,配置主要是Realm的管理認證
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工廠,設置對應的過濾條件和跳轉條件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> map = new HashMap<>();
map.put("/test/**","anon");
map.put("/public/**","anon");
map.put("/plugin/**","anon");
//登出
map.put("/logout", "logout");
//對所有用戶認證
map.put("/admin/**", "authc");
map.put("/user/**", "authc");
//登錄
shiroFilterFactoryBean.setLoginUrl("/login/index.html");
//首頁
shiroFilterFactoryBean.setSuccessUrl("/index");
//錯誤頁面,認證不通過跳轉
shiroFilterFactoryBean.setUnauthorizedUrl("/login/index.html");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//加入註解的使用,不加入這個註解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
三、編輯登錄功能,測試功能是否正常。
1.編輯通用的數據返回實體。ReturnData.java
會使用枚舉的話這裏也可以用上。
public class ReturnData {
private int code;
private String msg;
private Object date;
public ReturnData() {
}
public ReturnData(int code, String msg, Object date) {
this.code = code;
this.msg = msg;
this.date = date;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getDate() {
return date;
}
public void setDate(Object date) {
this.date = date;
}
}
編輯登錄控制器及相應的權限測試方法。SysLoginController.java
package cn.mvapi.xiaobao.common.system.controller;
import cn.mvapi.xiaobao.common.system.entity.ReturnData;
import cn.mvapi.xiaobao.common.system.entity.SysUser;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
//import com.sun.jndi.toolkit.url.UrlUtil;
//import org.apache.commons.codec.net.URLCodec;
@Controller
public class SysLoginController {
@ResponseBody
@RequestMapping("/login")
public ReturnData login(SysUser user) {
//添加用戶認證信息
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
user.getUsername(),
user.getPassword()
);
String error="";
try {
//進行驗證,這裏可以捕獲異常,然後返回對應信息
subject.login(usernamePasswordToken);
// subject.checkRole("admin");
// subject.checkPermissions("query", "add");
} catch (AuthenticationException e) {
//e.printStackTrace();
// return "賬號或密碼錯誤!";
return new ReturnData(201,"賬號或密碼錯誤!",null);
} catch (AuthorizationException e) {
// e.printStackTrace();
return new ReturnData(202,"您沒有權限!",null);
// return "沒有權限";
}
return new ReturnData(200,"登錄成功!",null);
}
//註解驗角色和權限
@RequiresPermissions("sys:role:delete")
@RequestMapping("/delete")
@ResponseBody
public String index() {
return "delete";
}
@RequiresPermissions("sys:user:save")
@RequestMapping("/save")
@ResponseBody
public String save() {
return "save";
}
//@RequiresPermissions("sys:user:save")
@RequiresRoles("管理員")
@RequestMapping("/role")
@ResponseBody
public String role() {
return "role";
}
@RequiresPermissions("sys:role:otherpermission")
@RequestMapping("/otherPermission")
@ResponseBody
public String others() {
return "用戶不存在的權限";
}
@RequiresRoles("otherRoles")
@RequestMapping("/otherRoles")
@ResponseBody
public String otherRoles() {
return "用戶不存在的角色";
}
}
啓動項目測試功能是否正常。
未登錄情況下訪問這裏會拋出錯誤http://localhost:8081/save
訪問登錄接口:http://localhost:8081/login/?username=admin&password=123
提示登錄成功後再次訪問上面接口 ,界面顯示save代表正常。
訪問http://localhost:8081/otherPermission
和http://localhost:8081/otherRoles 系統會拋出錯誤,因爲當前用戶沒有這個角色和權限。
本次教程結束!
上一章:https://blog.csdn.net/qq_41780372/article/details/104823854
下一章:https://blog.csdn.net/qq_41780372/article/details/105096733
github地址:https://github.com/xiaobaos/springboot
碼雲地址:https://gitee.com/xiaobaomeat/springboot
項目優先更新到github上面。
下一章:引入界面。