/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@Data
public class SysUser {
private Integer userId;
private String userName;
private String password;
private String userRemarks;
}
SysRole.class
import lombok.Data;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@Data
public class SysRole {
private String roleId;
private String roleName;
private String roleRemarks;
}
SysPermissions.java
import lombok.Data;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@Data
public class SysPermissions {
private Integer perId;
private String permissionsName;
private String perRemarks;
}
实体类创建完毕,先不用管那些操作表的增删改查。
核心使用环节, 创建ShiroConfig.java :
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;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@Configuration
public class ShiroConfig {
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
defaultAAP.setProxyTargetClass(true);
return defaultAAP;
}
//将自己的验证方式加入容器
@Bean
public UserRealm myShiroRealm() {
UserRealm userRealm = new UserRealm();
return userRealm;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//对url的过滤筛选
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> map = new HashMap<>();
//登出
map.put(“/logout”, “logout”);
//对所有用户认证
map.put(“/**”, “authc”);
//登录
shiroFilterFactoryBean.setLoginUrl(“/login”);
//成功登录后跳转的url
//shiroFilterFactoryBean.setSuccessUrl(“/xxxx”);
//错误页面,认证不通过跳转
// shiroFilterFactoryBean.setUnauthorizedUrl(“/error”);
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
创建自定义的权限审核处理类,UserRealm.java(涉及到数据库的查询文章后面有写):
import com.jc.shiro.pojo.SysUser;
import com.jc.shiro.service.LoginService;
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;
import java.util.List;
import java.util.Map;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
public class UserRealm extends AuthorizingRealm {
@Autowired
private LoginService loginService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String userName = (String) principalCollection.getPrimaryPrincipal();
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
List<Map<String, Object>> powerList = loginService.getUserPower(userName);
System.out.println(powerList.toString());
for (Map<String, Object> powerMap : powerList) {
//添加角色
simpleAuthorizationInfo.addRole(String.valueOf(powerMap.get(“roleName”)));
//添加权限
simpleAuthorizationInfo.addStringPermission(String.valueOf(powerMap.get(“permissionsName”)));
}
return simpleAuthorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
}
//获取用户信息
String userName = authenticationToken.getPrincipal().toString();
//根据用户名去数据库查询用户信息
SysUser sysUser = loginService.queryUser(userName);
if (sysUser == null) {
//这里返回后会报出对应异常
return null;
} else {
//这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userName, sysUser.getPassword().toString(), getName());
return simpleAuthenticationInfo;
}
}
}
然后是我们的登录接口,这里融合自己项目的帐号加密方法,LoginController.java:
import com.jc.shiro.service.LoginService;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@Controller
public class LoginController {
@Autowired
LoginService loginService;
@ResponseBody
@GetMapping(“/login”)
public String login(@RequestParam(“userName”) String userName, @RequestParam(“password”) String password) {
//添加用户认证信息
Subject subject = SecurityUtils.getSubject();
//自己系统的密码加密方式 ,这里简单示例一下MD5
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userName, md5Password);
try {
//进行验证,AuthenticationException可以catch到,但是AuthorizationException因为我们使用注解方式,是catch不到的,所以后面使用全局异常捕抓去获取
subject.login(usernamePasswordToken);
} catch (AuthenticationException e) {
e.printStackTrace();
return “账号或密码错误!”;
} catch (AuthorizationException e) {
e.printStackTrace();
return “没有权限”;
}
return “login success”;
}
}
其中用到了一个根据用户登录帐号去查询对应的角色权限信息,也就是文章开头我们设计的查询。
mapper层:
LoginMapper.java
import com.jc.shiro.pojo.SysUser;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@Mapper
public interface LoginMapper {
SysUser queryUser(String userName );
List<Map<String,Object>> getUserPower(String userName);
}
loginMapper.xml:
<?xml version="1.0" encoding="UTF-8" ?>SELECT *
FROM sys_user
WHERE userName=#{userName}
SELECT user.userId ,user.userName,role.roleName,role.roleId,per.permissionsName ,per.perId,per.perRemarks
FROM sys_user AS user,
sys_role AS role,
sys_permissions AS per,
role_per,
user_role
WHERE user.userName=#{userName}
AND user.userId=user_role.userId
AND user_role.roleId=role.roleId
AND role_per.roleId=role.roleId
AND role_per.perId=per.perId
然后是service层:
LoginService.java
import com.jc.shiro.pojo.SysUser;
import java.util.List;
import java.util.Map;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
public interface LoginService {
SysUser queryUser(String userName );
List<Map<String,Object>> getUserPower(String userName );
}
LoginServiceImpl.java
import com.jc.shiro.mapper.LoginMapper;
import com.jc.shiro.pojo.SysUser;
import com.jc.shiro.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@Service
public class LoginServiceImpl implements LoginService {
@Autowired
LoginMapper loginMapper;
@Override
public SysUser queryUser(String userName) {
return loginMapper.queryUser(userName);
}
@Override
public List<Map<String, Object>> getUserPower(String userName) {
return loginMapper.getUserPower(userName);
}
}
最后再补上一个异常全局控制器,MyExceptionHandler.java:
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@ControllerAdvice
@Slf4j
public class MyExceptionHandler {
@ExceptionHandler
@ResponseBody
public String ErrorHandler(AuthorizationException e) {
log.error(“权限校验失败!”, e);
return “您暂时没有权限,请联系管理员!”;
}
}
到这里,已经整合完毕,接下来是我们的使用,后端的校验我们采取shiro提供的注解的方式去使用:
@RequiresRoles(“xxx”)
@RequiresPermissions(“xxx”)
我们简单模拟导出数据功能模块,ExportController.java:
暂时只提供了一个导出接口,而这个导出接口需要用户拥有 admin 角色 以及 exportUserInfo 权限,也就是代码里注解的参数
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@RestController
public class ExportController {
@RequiresRoles(“admin”)
@RequiresPermissions(“exportUserInfo”)
@ResponseBody
@RequestMapping(“/export”)
public String export() {
return “u can export !”;
}
}
再来模拟日志功能模块,LogController.java:
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
/**
-
@Author : JCccc
-
@CreateTime : 2020/4/24
-
@Description :
**/
@RestController
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。
如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-ZOHxE5JP-1712680710424)]
[外链图片转存中…(img-Xae1SOcB-1712680710425)]
[外链图片转存中…(img-hvLULSEZ-1712680710425)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
总体来说,如果你想转行从事程序员的工作,Java开发一定可以作为你的第一选择。但是不管你选择什么编程语言,提升自己的硬件实力才是拿高薪的唯一手段。
如果你以这份学习路线来学习,你会有一个比较系统化的知识网络,也不至于把知识学习得很零散。我个人是完全不建议刚开始就看《Java编程思想》、《Java核心技术》这些书籍,看完你肯定会放弃学习。建议可以看一些视频来学习,当自己能上手再买这些书看又是非常有收获的事了。
[外链图片转存中…(img-lHomTFX8-1712680710425)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!