SpringBoot与Shiro整合-权限管理实战。
打开Eclipse,new Maven Project--Create a simple project
输入项目相关信息,Packing 选择为jar,点击Finish。
修改项目的编译环境为1.8
打开项目的pom.xml
1.8
添加之后--右击项目-Maven-update Project
添加父级依赖
打开pom.xml
org.springframework.boot
spring-boot-starter-parent
1.5.4.RELEASE
添加项目依赖
打开pom.xml
org.springframework.boot
spring-boot-starter-web
完整pom.xml
4.0.0
org.springframework.boot
spring-boot-starter-parent
1.5.4.RELEASE
com.badao.springboot
springboot-shiro
0.0.1-SNAPSHOT
org.springframework.boot
spring-boot-starter-web
1.8
在src/main/java下新建UserController
代码:
package com.badao.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class UserController {
/***
* usercontroller测试
*/
@RequestMapping("/hello")
@ResponseBody
public String hello() {
System.out.println("**********************hello");
return "hello";
}
}
新建项目启动类Application.java,要与UserController同级
package com.badao;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* springboot启动类
* @author badao
* @Description:
* @Time:2019年5月19日 下午4:20:07
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
运行启动类
启动效果
打开浏览器访问
http://localhost:8080/hello
打开pom.xml
org.springframework.boot
spring-boot-starter-thymeleaf
在src/main/resources下新建templates目录,目录下新建test.html
代码:
Thymeleaf 使用
注意:
在thymeleaf3.0以前对页面标签语法要求比较严格开始标签必须有结束标签。
所以这里手动加上结束标签。
或者这里升级thymeleaf为3.0或更高。
具体参照:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/90344773
在UserController中新建测试方法
/***
* Thymeleaf测试
*/
@RequestMapping("/testThymeleaf")
public String testThymeleaf(Model model) {
model.addAttribute("username","badao");
return "test";
}
运行效果
启动启动类,打开浏览器输入:
http://localhost:8080/testThymeleaf
新建包shiro,包下新建UserRealm.java
package com.badao.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/***
* 自定义Realm
* @author Administrator
* @Description:
* @Time:2019年5月19日 下午6:34:50
*/
public class UserRealm extends AuthorizingRealm{
/***
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
System.out.println("执行授权逻辑");
return null;
}
/***
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("执行认证逻辑");
return null;
}
}
shiro包下新建ShiroConfig.java配置类
package com.badao.shiro;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/***
* Shiro配置类
* @author Administrator
* @Description:
* @Time:2019年5月19日 下午6:33:48
*/
@Configuration
public class ShiroConfig {
/***
* 创建ShiroFilterFactoryBean
* @return
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
return shiroFilterFactoryBean;
}
/***
* 创建DefaultWebSecurityManager
* @return
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联realm
securityManager.setRealm(userRealm);
return securityManager;
}
/***
* 创建Realm
* @return
*/
@Bean(name="userRealm")
public UserRealm getRealm() {
return new UserRealm();
}
}
注:
通过@Bean(name="userRealm")实现添加到spring容器,然后通过@Qualifier("userRealm")去引用。
打开test.html,添加两个超链接。
Thymeleaf 使用
添加
更新
注:
进行页面的跳转时不能直接跳转到具体的页面,必须经过controller跳转。
templates下新建user目录,目录下新建add.html
添加用户
开始添加用户
再新建update.html
编辑用户
开始编辑用户
来到UserController中,添加跳转页面方法。
/***
* 跳转到add
*/
@RequestMapping("/add")
public String add() {
return "user/add";
}
/***
* 跳转到update
*/
@RequestMapping("/update")
public String update() {
return "user/update";
}
运行项目,打开浏览器输入:
http://localhost:8080/testThymeleaf
需求:
访问首页即testThymeleaf时不进行验证,访问添加和编辑时进行拦截跳转到登录页面。
template下新建login.html
登录页面
请登录
打开ShiroConfig配置文件
添加Shiro内置过滤器:
1.anon:无需认证可以访问。
2.authc:必须认证才可以 访问。
3.user:如果使用rememberMe的功能可以直接访问。
4.perms:该资源必须得到资源权限才可以访问。
5.role:该资源必须得到角色权限才可以访问。
在getShiroFilterFactoryBean中:
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加Shiro内置过滤器
Map filterMap = new LinkedHashMap();
filterMap.put("/add", "authc");
filterMap.put("/update", "authc");
//上面两行可以用通配符来配置
//filterMap.put("/*", "authc");
//不拦截首页
filterMap.put("/testThymeleaf", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
//修改调整的登录页面
shiroFilterFactoryBean.setLoginUrl("/login");
return shiroFilterFactoryBean;
}
在UserController中添加登录跳转
/***
* 跳转到login
*/
@RequestMapping("/login")
public String login() {
return "login";
}
启动项目,输入:
http://localhost:8080/testThymeleaf
效果
编写login.html
登录页面
请登录
UserController中添加登录方法
/***
* login
*/
@RequestMapping("/dologin")
public String dologin(String name,String password,Model model) {
/***
* 使用Shiro编写认证操作
*
*/
//1.获取Subject
Subject subject = SecurityUtils.getSubject();
//2.封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
//3.执行登录方法
try {
//登录成功,没有异常代表登录成功
//login方法会来到UserRealm中的执行认证的方法
subject.login(token);
return "redirect:/testThymeleaf";
}catch (UnknownAccountException e) {
//登录失败:用户名不存在
model.addAttribute("msg","用户名不存在");
return "/login";
}catch (IncorrectCredentialsException e){
//登录失败:密码不正确
model.addAttribute("msg","密码不正确");
return "/login";
}
}
注:
1.subject.login(token)会自动找到自定义Realm中的执行认证的方法。
2.没有异常就是登录成功,出现UnknownAccountException 就是用户名不正确,出现IncorrectCredentialsException 就是密码不正确。
修改UserRealm
/***
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken args) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("执行认证逻辑");
//假设数据库用户名和密码
String name = "badao";
String password = "123";
//1.判断用户名
UsernamePasswordToken token = (UsernamePasswordToken) args;
if(!token.getUsername().equals(name)){
//用户名不存在
//shiro底层会抛出UnknownAccountException
return null;
}
//2.判断密码
//编写shiro判断逻辑
return new SimpleAuthenticationInfo("",password,"");
}
在配置文件中给登录放行
Map filterMap = new LinkedHashMap();
filterMap.put("/add", "authc");
filterMap.put("/update", "authc");
//上面两行可以用通配符来配置
//filterMap.put("/*", "authc");
//不拦截首页
filterMap.put("/testThymeleaf", "anon");
filterMap.put("/dologin", "anon");
运行项目,打开浏览器输入:
http://localhost:8080/testThymeleaf
效果
打开pom.xml
com.alibaba
druid
1.0.9
mysql
mysql-connector-java
8.0.11
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1
新建表Users
在src/main/resources下新建application.properties
名字与位置必须一致。
代码:
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shirotest?useUnicode=true&characterEncoding=UTF-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123
#配置数据源
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#配置别名
mybatis.type-aliases-package=com.badao.entity
新建entity包,包下新建User.java
package com.badao.entity;
public class User {
int id;
String userName;
String password;
public int getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return userName;
}
public void setUsername(String username) {
this.userName = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
新建mapper包,包下新建UserMapper接口
package com.badao.mapper;
import com.badao.entity.User;
public interface UserMapper {
public User findByName(String name);
}
再在此包新新建UserMapper.xml
新建service包,包下新建UserService接口
package com.badao.service;
import com.badao.entity.User;
public interface UserService {
public User findByName(String name);
}
再在此包下新建UserServiceImpl
package com.badao.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.badao.entity.User;
import com.badao.mapper.UserMapper;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User findByName(String name) {
// TODO Auto-generated method stub
return userMapper.findByName(name);
}
}
打开UserController,添加如下登录方法。
/***
* 跳转到login
*/
@RequestMapping("/login")
public String login() {
return "login";
}
/***
* login
*/
@RequestMapping("/dologin")
public String dologin(String name,String password,Model model) {
/***
* 使用Shiro编写认证操作
*
*/
//1.获取Subject
Subject subject = SecurityUtils.getSubject();
//2.封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
//3.执行登录方法
try {
//登录成功,没有异常代表登录成功
//login方法会来到UserRealm中的执行认证的方法
subject.login(token);
return "redirect:/testThymeleaf";
}catch (UnknownAccountException e) {
//登录失败:用户名不存在
model.addAttribute("msg","用户名不存在");
return "/login";
}catch (IncorrectCredentialsException e){
//登录失败:密码不正确
model.addAttribute("msg","密码不正确");
return "/login";
}
}
打开UserRealm.java,修改为:
/***
* 执行认证逻辑
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken args) throws AuthenticationException {
// TODO Auto-generated method stub
System.out.println("执行认证逻辑");
//假设数据库用户名和密码
/*String name = "badao";
String password = "123";*/
UsernamePasswordToken token = (UsernamePasswordToken) args;
User user = userService.findByName(token.getUsername());
//1.判断用户名
if(user==null){
//用户名不存在
//shiro底层会抛出UnknownAccountException
return null;
}
//2.判断密码
//编写shiro判断逻辑
return new SimpleAuthenticationInfo("",user.getPassword(),"");
}
打开ShiroConfig,放开登录页面
Map filterMap = new LinkedHashMap();
filterMap.put("/add", "authc");
filterMap.put("/update", "authc");
//上面两行可以用通配符来配置
//filterMap.put("/*", "authc");
//不拦截首页
filterMap.put("/testThymeleaf", "anon");
filterMap.put("/login", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
请登录
打开Application.java,添加@MapperScan("com.badao.mapper"):
@SpringBootApplication
@MapperScan("com.badao.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
打开ShiroConfig配置文件,添加授权过滤器。
//授权过滤器
//注意:当授权拦截后,shiro会自动跳转到未授权页面
filterMap.put("/add", "perms[user:add]");
shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
打开UserController,添加未授权页面跳转
/***
* 跳转到未授权页面
*/
@RequestMapping("/login")
public String login() {
return "login";
}
在templates下新建unAuth.html
没有授权
没有授权
/***
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
System.out.println("执行授权逻辑");
//给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加资源的授权字符串
info.addStringPermission("user:add");
return info;
}
注意:
添加资源的授权字符串要与上面进行拦截的字符串一致才能跳过拦截。
效果:
为了简单的进行测试,不再建立角色表与权限表。
直接添加权限列。
授予badao用户 user:add权限
授予liumang用户 user:update权限
package com.badao.entity;
public class User {
int id;
String userName;
String password;
public String getPerms() {
return perms;
}
public void setPerms(String perms) {
this.perms = perms;
}
String perms;
public int getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return userName;
}
public void setUsername(String username) {
this.userName = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
public User findById(int id);
public User findById(int id);
@Override
public User findById(int id) {
// TODO Auto-generated method stub
return userMapper.findById(id);
}
打开Shiroconfig.java
//注意:当授权拦截后,shiro会自动跳转到未授权页面
filterMap.put("/add", "perms[user:add]");
filterMap.put("/update", "perms[user:update]");
打开UserRealm.java
/***
* 执行授权逻辑
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
System.out.println("执行授权逻辑");
//给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加资源的授权字符串
//info.addStringPermission("user:add");
//获取当前登录用户
Subject subject = SecurityUtils.getSubject();
User user = (User)subject.getPrincipal();
userService.findById(user.getId());
info.addStringPermission(user.getPerms());
return info;
}
注:
User user = (User)subject.getPrincipal();这句中的getPrincipal()就是获取下面执行逻辑认证的
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
第一个参数。
打开pom.xml
com.github.theborakompanioni
thymeleaf-extras-shiro
2.0.0
打开ShiroConfig
/***
* 配置ShiroDialect 用于thymeleaf和Shiro便签配合使用
*/
@Bean
public ShiroDialect getShiroDialect() {
return new ShiroDialect();
}
打开test.html
Thymeleaf 使用
登录
https://download.csdn.net/download/badao_liumang_qizhi/11194439