SpringBoot整合shiro从初恋到失恋
建个项目或者模块,目录结构如下
在pom.xml中加入shiro依赖,其他依赖自行添加(lombok,jpa,mybatis,web,thymeleaf等)
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
application.properties中的配置
##端口号 server.port=8888 ##数据库配置 ##数据库地址 spring.datasource.url=jdbc:mysql://localhost:3306/shiro?characterEncoding=utf8&useSSL=false\ &serverTimezone=GMT%2B8 ##数据库用户名 spring.datasource.username=root ##数据库密码 spring.datasource.password=Panbing936@ ##数据库驱动 spring.datasource.driver-class-name=com.mysql.jdbc.Driver ##validate 加载hibernate时,验证创建数据库表结构 ##create 每次加载hibernate,重新创建数据库表结构,这就是导致数据库表数据丢失的原因。 ##create-drop 加载hibernate时创建,退出是删除表结构 ##update 加载hibernate自动更新数据库结构 ##validate 启动时验证表的结构,不会创建表 ##none 启动时不做任何操作 spring.jpa.hibernate.ddl-auto=update ##控制台打印sql spring.jpa.show-sql=true # 建议在开发时关闭缓存,不然没法看到实时页面 spring.thymeleaf.cache=false ##去除thymeleaf的html严格校验 spring.thymeleaf.mode=LEGACYHTML5 #没下面这行配置就会报这个错误 #Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
实体类SysMenu.java中的代码
@Entity @Data public class SysMenu implements Serializable { @Id @GeneratedValue private Integer menuId; private String menuName; @ManyToMany @JoinTable(name = "SysRoleMenu", joinColumns = {@JoinColumn(name = "menuId")}, inverseJoinColumns = {@JoinColumn(name = "roleId")}) private List<SysRole> roleList; }
实体类SysRole.java中的代码
@Entity @Data public class SysRole implements Serializable { @Id @GeneratedValue private Integer roleId; private String roleName; //多对多关系 @ManyToMany(fetch = FetchType.EAGER) @JoinTable(name = "SysRoleMenu", joinColumns = {@JoinColumn(name = "roleId")}, inverseJoinColumns = {@JoinColumn(name = "menuId")}) private List<SysMenu> menuList; //多对多关系 @ManyToMany @JoinTable(name = "SysUserRole", joinColumns = {@JoinColumn(name = "roleId")}, inverseJoinColumns = {@JoinColumn(name = "userId")}) private List<SysUser> userList;// 一个角色对应多个用户 }
实体类SysUser.java中的代码
@Entity @Data public class SysUser implements Serializable { @Id @GeneratedValue private Integer userId; @NotEmpty private String userName; @NotEmpty private String passWord; //多对多关系 @ManyToMany(fetch = FetchType.EAGER) //急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载 //FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载 @JoinTable(name = "SysUserRole", joinColumns = {@JoinColumn(name = "userId")}, inverseJoinColumns = {@JoinColumn(name = "roleId")}) private List<SysRole> roleList;// 一个用户具有多个角色 }
接口UserRepository.java中的代码
public interface UserRepository extends CrudRepository<SysUser,Long> { SysUser findByUserName(String username); }
下面的代码才是shiro相关的
MyshiroRealm.java
public class MyShiroRealm extends AuthorizingRealm { @Resource private UserRepository userRepository; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); SysUser userInfo = (SysUser)principals.getPrimaryPrincipal(); for(SysRole role:userInfo.getRoleList()){ authorizationInfo.addRole(role.getRoleName()); for(SysMenu menu:role.getMenuList()){ authorizationInfo.addStringPermission(menu.getMenuName()); } } return authorizationInfo; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //获得当前用户的用户名 String username = (String)token.getPrincipal(); System.out.println(token.getCredentials()); //根据用户名找到对象 //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法 SysUser userInfo = userRepository.findByUserName(username); if(userInfo == null){ return null; } //这里会去校验密码是否正确 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( userInfo, //用户名 userInfo.getPassWord(),//密码 getName() ); return authenticationInfo; } }
ShiroConfig.java
@Configuration public class ShiroConfig { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { logger.info("启动shiroFilter--时间是:" + new Date()); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //shiro拦截器 Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 --> // 配置不被拦截的资源及链接 filterChainDefinitionMap.put("/static/**", "anon"); // 退出过滤器 filterChainDefinitionMap.put("/logout", "logout"); //配置需要认证权限的 filterChainDefinitionMap.put("/**", "authc"); // 如果不设置默认会自动寻找Web工程根目录下的"/login"页面,即本文使用的login.html shiroFilterFactoryBean.setLoginUrl("/login"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/index"); //未授权界面 shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } //自定义身份认证Realm(包含用户名密码校验,权限校验等) @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); return myShiroRealm; } @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); return securityManager; } //开启shiro aop注解支持,不开启的话权限验证就会失效 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } //配置异常处理,不配置的话没有权限后台报错,前台不会跳转到403页面 @Bean(name="simpleMappingExceptionResolver") public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() { SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver(); Properties mappings = new Properties(); mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理 mappings.setProperty("UnauthorizedException","403"); simpleMappingExceptionResolver.setExceptionMappings(mappings); // None by default simpleMappingExceptionResolver.setDefaultErrorView("error"); // No default simpleMappingExceptionResolver.setExceptionAttribute("ex"); // Default is "exception" return simpleMappingExceptionResolver; } }
thymeleaf的页面代码
index.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> index <br/> <form th:action="@{/logout}" method="post"> <p><input type="submit" value="重新登录"/></p> </form> <form th:action="@{/select}" method="get"> <p><input type="submit" value="查看"/></p> </form> <form th:action="@{/delete}" method="get"> <p><input type="submit" value="删除"/></p> </form> </body> </html>
login.html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> <head> <meta charset="UTF-8"> <title>Login</title> </head> <body> 错误信息:<h4 th:text="${msg}"></h4> <form action="" method="post"> <p>账号:<input type="text" name="username" value="dalaoyang"/></p> <p>密码:<input type="text" name="password" value="123"/></p> <p><input type="submit" value="登录"/></p> </form> </body> </html>
另外三个跳转页面就不贴出来了,panpan账号登录可以查看和删除,用xiaoli账号登录则只有查看而没有删除的权限,代码见下面,sql文件在resources包下
github代码
相关推荐
visionzheng 2020-04-20
杜鲁门 2020-11-05
luckyxl0 2020-08-16
Dullonjiang 2020-08-09
xclxcl 2020-08-03
zmzmmf 2020-08-03
MicroBoy 2020-08-02
ganjing 2020-08-02
likesyour 2020-08-01
zmzmmf 2020-07-09
MicroBoy 2020-07-05
zzhao 2020-06-26
子云 2020-06-18
visionzheng 2020-06-07
neweastsun 2020-06-04
ErixHao 2020-06-03
GDreams0 2020-06-01
ganjing 2020-05-29