目录
1.项目结构
2.pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wo</groupId>
<artifactId>home_shiro_springboot</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--shiro的包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!--JPA-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- swagger2 的依赖/自动生成接口文档以及自测的工具-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
</project>
3.application.yml
server:
port: 8088
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql:///qf?useUnicode=true&characterEncoding=utf8&useSSL=false
jpa:
database: mysql
show-sql: true
generate-ddl: true
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
4.config
4.1.ShiroConfig
@Configuration
public class ShiroConfig {
//1.获取到我们的myrealm
@Bean(name = "myRealm")
public MyRealm myRealm(@Qualifier("hashedCredentialsMatcher")HashedCredentialsMatcher matcher){
MyRealm myRealm = new MyRealm();
myRealm.setAuthorizationCachingEnabled(false);
myRealm.setCredentialsMatcher(matcher);
return myRealm;
}
//2.声明securityManager
@Bean(name = "defaultWebSecurityManager")
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm){
//shiro核心
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//在核心中设置我们自定义的realm
defaultWebSecurityManager.setRealm(myRealm);
return defaultWebSecurityManager;
}
//3.工厂
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//权限
//声明没有权限的情况下走的接口名称
shiroFilterFactoryBean.setUnauthorizedUrl("/unauth");
// //告诉shiro有用什么权限可以访问什么接口
//如果不加注解不加map,默认没有权限控制
// Map map = new HashMap<>();
// map.put("/findAll","perms[user_findAll]");
// map.put("/deleteById","perms[user_delete]");
// //将访问接口的权限放置到shiroFileter中
// shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//使用aop注解模式来使用权限
//使用aop扫描包含shiro注解的类
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
//将WebSecurityManager 交给spring aop来进行管理
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("defaultWebSecurityManager")DefaultWebSecurityManager defaultWebSecurityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* 密码校验规则HashedCredentialsMatcher
* 这个类是为了对密码进行编码的 ,
* 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,
* 这个类也负责对form里输入的密码进行编码
* 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher
*/
@Bean("hashedCredentialsMatcher")
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密方式为MD5
credentialsMatcher.setHashAlgorithmName("MD5");
//加密次数
credentialsMatcher.setHashIterations(1);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
return credentialsMatcher;
}
}
4.2.Swagger2Config(接口文档)
//标注当前工程是一个配置类
@Configuration
//开启swagger的配置
@EnableSwagger2
public class Swagger2Config {
//将该Docket交给了spring中的ioc
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// swagger进行包扫描,扫描你当前的controller层路径
.apis(RequestHandlerSelectors.basePackage("com.wo.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("java-swagger")
.description("swagger接入教程,简单好用")
//服务条款网址
.version("1.0")
.build();
}
}
5.controller
5.1PermissionExcepitonController
//控制器增强 异常捕获类
@ControllerAdvice
public class PermissionExcepitonController {
//告诉控制器 捕捉什么类型的异常 以及对异常进行处理
@ExceptionHandler(value = AuthorizationException.class)
public String excepiton(){
return "unauth";
}
@ExceptionHandler(value = ArithmeticException.class)
public String urithmeticException(){
return "error";
}
}
5.2PersonController
@Controller
public class PersonController {
@Autowired
PersonService personService;
@RequestMapping("/tologin")
public String tologin(){
return "login";
}
@RequestMapping("/login")
public String login(TbSysUser tbSysUser){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(tbSysUser.getLoginName(), tbSysUser.getPassword());
try {
subject.login(token);
}catch (IncorrectCredentialsException ini){
System.out.println(ini.getMessage());
}
if (subject.isAuthenticated()){
return "redirect:findAll";
}else{
return "login";
}
}
@RequestMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "login";
}
@RequiresPermissions(value = {"user_findAll"})
@RequestMapping("/findAll")
public ModelAndView findAll(){
List<Person> list = personService.findAll();
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("list",list);
modelAndView.setViewName("index");
return modelAndView;
}
@RequiresPermissions(value = {"user_update"})
@RequestMapping("/findById")
public ModelAndView findById(@RequestParam ("id")int id){
Person person = personService.findById(id);
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("person",person);
modelAndView.setViewName("update");
return modelAndView;
}
@RequiresPermissions(value = {"user_delete"})
@RequestMapping("/deleteById")
public String deleteById(@RequestParam ("id")int id){
personService.deleteById(id);
return "redirect:/findAll";
}
@RequiresPermissions(value = {"user_update"})
@RequestMapping("/update")
public String update(Person person){
personService.update(person);
return "redirect:/findAll";
}
@RequiresPermissions(value = {"user_update"})
@RequestMapping("/goUpadatePage")
public ModelAndView goUpadatePage(){
Person person=new Person();
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("person",person);
modelAndView.setViewName("update");
return modelAndView;
}
@RequestMapping("/unauth")
public String unauth(){
return "unauth";
}
}
6.dao和mapper
6.1 PersonDao
public interface PersonDao extends JpaRepository<Person,Integer>{
}
6.2 TbSysPermissionDao
@Mapper
public interface TbSysPermissionDao {
List<TbSysPermissions> findPermissonByLoginName(@Param("loginName") String loginName);
}
6.3 TbUserDao
@Mapper
public interface TbUserDao {
TbSysUser login(@Param("loginName") String loginName);
}
6.4 TbPermissionMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wo.dao.TbSysPermissionDao">
<resultMap id="BaseResult" type="com.wo.pojo.TbSysPermissions">
<id property="permissionId" column="permission_id"></id>
<result property="perName" column="per_name"></result>
</resultMap>
<select id="findPermissonByLoginName" resultMap="BaseResult">
SELECT sp.per_name from tb_sys_user su,tb_sys_role sr,tb_sys_permission sp, tb_user_role ur,tb_role_permission rp
where su.userid=ur.user_id
and ur.role_id = sr.role_id
and sr.role_id = rp.role_id
and rp.permission_id = sp.permission_id
and su.login_name=#{loginName};
</select>
</mapper>
6.5 TbUserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wo.dao.TbUserDao">
<resultMap id="BaseResult" type="com.wo.pojo.TbSysUser">
<id property="userid" column="userid"></id>
<result property="loginName" column="login_name"></result>
<result property="password" column="password"></result>
</resultMap>
<select id="login" resultMap="BaseResult">
select * from tb_sys_user where login_name = #{loginName}
</select>
</mapper>
7.pojo
7.1 Person
@Data
@Entity
@Table(name = "tb_person")
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private int age;
private int is_marry;
private String user_name;
private int sex;
private String address;
@DateTimeFormat(pattern = "yyyy-MM-ss")
private Date birthday;
}
7.2 TbSysPermissions
@Data
public class TbSysPermissions {
private Integer permissionId;
private String perName;
}
7.3 TbSysUser
@Data
public class TbSysUser {
private Integer userid;
private String loginName;
private String password;
}
8.service
8.1 PersonService
public interface PersonService {
public List<Person> findAll();
public Person findById(int id);
public void deleteById(int id);
public void update(Person person);
}
8.2 PersonServiceImpl
@Service
public class PersonServiceImpl implements PersonService {
@Autowired
PersonDao personDao;
@Override
public List<Person> findAll() {
return personDao.findAll();
}
@Override
public Person findById(int id) {
Optional<Person> byId = personDao.findById(id);
if(byId.isPresent()){
Person person=byId.get();
return person;
}
return null;
}
@Override
public void deleteById(int id) {
personDao.deleteById(id);
}
@Override
public void update(Person person) {
personDao.saveAndFlush(person);
}
}
9. shiro
MyRealm
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
TbUserDao tbUserDao;
@Autowired
TbSysPermissionDao tbSysPermissionDao;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取到前端传输用户名
String username = (String) principalCollection.getPrimaryPrincipal();
//使用用户名查询该用户的权限
List<TbSysPermissions> permissonByLoginName = tbSysPermissionDao.findPermissonByLoginName(username);
//声明set进行去重
HashSet<String> set=new HashSet<>();
for (TbSysPermissions tb:permissonByLoginName) {
set.add(tb.getPerName());
}
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(set);
return simpleAuthorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获得到用户名
String username = (String) authenticationToken.getPrincipal();
//使用用户名查询密码
TbSysUser user = tbUserDao.login(username);
//不使用加盐加密
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, user.getPassword(), getName());
//使用加盐加密
//SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, user.getPassword(),ByteSource.Util.bytes("wang"), getName());
return simpleAuthenticationInfo;
}
}
10.SpringbootWangApplication
@SpringBootApplication
public class SpringbootWangApplication {
//
public static void main(String[] args) {
SpringApplication.run(SpringbootWangApplication.class, args);
}
}
11.templates
11.1 error.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>您当前的操作有误,请稍后再试</h1>
</body>
</html>
11.2 index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<center>
<h1>=========王沁狄==========</h1>
<h2><a th:href="swagger-ui.html">接口页面-----<a href="/logout">退出登录</a></a></h2>
<a th:href="@{/goUpadatePage}">新增</a>
<table border="1">
<tr>
<th>序号</th>
<th>ID</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>生日</th>
<th>婚姻</th>
<th>地址</th>
<th>操作</th>
</tr>
<tr th:each="person,p:${list}">
<td th:text="${p.index+1}"></td>
<td th:text="${person.id}"></td>
<td th:text="${person.user_name}"></td>
<td th:text="${person.age}"></td>
<td>
<span th:if="${person.sex eq 1}">男</span>
<span th:if="${person.sex eq 0}">女</span>
</td>
<td th:text="${person.birthday}"></td>
<td>
<span th:if="${person.is_marry eq 1}">已婚</span>
<span th:if="${person.is_marry eq 0}">未婚</span>
</td>
<td th:text="${person.address}"></td>
<td>
<a th:href="@{'deleteById?id='+${person.id}}">删除</a>
<a th:href="@{'findById?id='+${person.id}}">修改</a>
</td>
</tr>
</table>
</center>
</body>
</html>
11.3 login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<center>
<form action="/login" method="post">
用户名:<input type="text" name="loginName"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="提交">
</form>
</center>
</body>
</html>
11.4 unauth.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>您没有权限,请联系管理员</h1>
</body>
</html>
11.5 update.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form th:action="@{/update}" th:method="post">
<input th:type="hidden" th:name="id" th:value="${person.id}">
姓名: <input th:type="text" th:name="user_name" th:value="${person.user_name}"><br/>
年龄: <input th:type="text" th:name="age" th:value="${person.age}"><br/>
性别: <input th:type="text" th:name="sex" th:value="${person.sex}"><br/>
生日: <input th:type="datetime-local" th:name="birthday" th:value="${person.birthday}"><br/>
婚姻: <input th:type="text" th:name="is_marry" th:value="${person.is_marry}"><br/>
地址: <input th:type="text" th:name="address" th:value="${person.address}"><br/>
<input th:type="submit" th:value="提交">
</form>
</body>
</html>