Create a SpringBoot project

1.

New –>Project–>Spring Initralizr Group:com.zb Artifact: Zbook Springboot version:2.0.4

2,

will

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
</dependency>
Copy the code

to

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
Copy the code

3. Project structure at this time

Maven clean, right-click ZbookApplication, and the project is up and running. It’s as simple as that, really out of the box.

RestFul APIS

1. Create a HomeController in the Controller package

package com.zb.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
    @RequestMapping("/")
    public String home(){
        return "Hello, Zbook!";
    }
}
Copy the code

Note: The difference between the RestController and Controller annotations is that RestController is the returned content (equivalent to adding @responseBody), whereas Controller is the returned page

Open the web page and type http://localhost:8080/ to see Hello,Zbook!

3. Integrate Thymleaf

1.

The above can be used as an interface to provide services. Suppose we want to develop a Web application, SpringBoot is integrated with ThymLeaf by default. Springboot is by convention more than by configuration. Let’s look at the convention for ThymLeaf. (1) Default static files (JS, CSS, We used bootstrap to render the page, as shown in the image below

login.html <! DOCTYPE HTML > < HTML XMLNS :th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title> Login </title> <link href="/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <form action="login_in" method="post" class="form-horizontal" role="form" > <div class="form-group"> <h2 class="col-sm-offset-5 </h2> </div> <div class="form-group"> <label for="username" class="col-sm-offset-3 col-sm-2 Control-label "> user name: </label> <div class="col-sm-3"> <input type="text" class="form-control" id="username" name="username" Placeholder =" please input username "/> </div> </div> <div class="form-group"> <label for="password" class="col-sm-offset-3 col-sm-2" Control - the label "> password: </label> <div class="col-sm-3"> <input type="text" class="form-control" id="password" name="password" Placeholder =" please input password "/> </div> <div > <div class="form-group"> <div class="col-sm-offset-5 col-sm-4"> <button </button> </div> </form> </div> <script SRC = "/ js/jquery - 2.2.1. Min. Js" > < / script > < script SRC = "/ js/bootstrap. Min. Js" > < / script > < / body > < / HTML >Copy the code

2. Write a LoginController

package com.zb.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { @RequestMapping("/login") public String login(){ return "login"; }}Copy the code

3, add dependence

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Copy the code

4,

Restart, http://localhost:8080/login will see the login page

4. Integrate Mybatis

1.

The SpringBoot configuration files are divided into two types: application.properties and Application.yml. Let’s change it to Application.yml to make it more intuitive

spring: application: name: myspringboot output: ansi: enabled: always profiles: active: dev thymeleaf: encoding: UTF-8 prefix: classpath:/templates/ server: tomcat: uri-encoding: UTF-8 max-connections: 500 min-spare-threads: 25 max-threads: 300 accept-count: 200 port: 8080 mybatis: type-aliases-package: com.zb.mapper mapper-locations: classpath:mapping/*.xml pagehelper: helper-dialect: mysql reasonable: true support-methods-arguments: true params: Count =countSql logging: level: com.zb.mapper: debug -- # config config Spring: profiles: dev datasource: url: jdbc:mysql://localhost:3306/zb_db? useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOverReadOnly=false&useSSL=false username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource filters: stat maxActive: 20 initialSize: 1 maxWait: 60000 minIdle: 1 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: select 'x' testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20Copy the code

2. Add dependencies

<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> < version > 1.3.2 < / version > < / dependency > < the dependency > < groupId > mysql < / groupId > <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>RELEASE</version> </dependency> <! <dependency> <groupId>com.github. Pagehelper </groupId> < artifactId > pagehelper - spring - the boot - starter < / artifactId > < version > 1.2.3 < / version > < / dependency >Copy the code

3, build table

CREATE datebase zb_db;
Copy the code
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `mobile` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `sex` varchar(255) DEFAULT NULL,
  `nickname` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Copy the code
insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(1, 'admin', '123456', '13918891675','[email protected]', 'male ',' administrator '); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(2, 'lisi2', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(3, 'lisi3', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(4, 'lisi4', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(5, 'lisi5', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(6, 'lisi6', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(7, 'lisi7', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(8, 'lisi8', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(9, 'lisi9', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(10, 'lisi10', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(11, 'lisi11', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(12, 'lisi12', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(13, 'lisi13', '123456', '13918891675','[email protected]', 'm', 'lisi1'); insert into `user`(id, username, password, mobile, email,sex, nickname) VALUES(14, 'lisi14', '123456', '13918891675','[email protected]', 'm', 'lisi1');Copy the code

4. Generate files automatically with MybatisGenerator

<? The XML version = "1.0" encoding = "utf-8"? > <! DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <! > <classPathEntry location="C:\Users\DELL\Downloads\mysql-connector-java-5.1.22-bin.jar"/> <context id="DB2Tables" targetRuntime="MyBatis3"> <commentGenerator> <property name="suppressDate" value="true"/> <! -- Whether to remove automatically generated comments true: yes: false: no --> < Property name="suppressAllComments" value="true"/> </commentGenerator> <! Database link URL, User name and password - > < jdbcConnection driverClass = ". Com. Mysql. JDBC Driver "connectionURL =" JDBC: mysql: / / 127.0.0.1 zb_db" userId="root" password="123456"> </jdbcConnection> <javaTypeResolver> <property name="forceBigDecimals" value="false"/> </javaTypeResolver> <! JavaModelGenerator targetPackage="com.zb.model" targetProject=" SRC /main/ Java "> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <! <sqlMapGenerator targetPackage="mapping" targetProject=" SRC /main/resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <! <javaClientGenerator type="XMLMAPPER" targetPackage="com.zb.mapper" targetProject=" SRC /main/ Java "> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <! DomainObjectName = entity class name --> <table tableName=" roLE_Permission" domainObjectName="RolePermission" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context> </generatorConfiguration>Copy the code

5. Add plugin to POM

<! Mybatis generator plugin -- <plugin> <groupId>org.mybatis. Generator </groupId> < artifactId > mybatis generator - maven plugin - < / artifactId > < version > 1.3.2 < / version > < configuration > <configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile> <overwrite>true</overwrite> <verbose>true</verbose> </configuration> </plugin>Copy the code

6. Generate a file with MVN mybatis-generator:generate -e command

Directory structure at this point

7, write the dao and the service, the controller, the mapper

Mapper adds several methods

@Select("Select * from user")
List<User> selectAll();

@Select("Select * from user where username = #{username} and password = #{password}")
User selectByUsernamePass(@Param("username") String username, @Param("password") String password);

@Select("Select * from user where username = #{username}")
User selectByUsername(@Param("username") String username);
Copy the code

The DAO and service are called normally, and here is the controller

package com.zb.controller; import com.github.pagehelper.PageInfo; import com.zb.model.User; import com.zb.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class UserController { @Autowired private UserService userService; @RequestMapping("/user") @ResponseBody public User getUserById(int id){ User user = userService.selectByPrimaryKey(id); return user; } @RequestMapping("/userlist") public String getUserList(Model model, PageInfo pageInfo){ int pageNum = (pageInfo.getPageNum() == 0)? 1 : pageInfo.getPageNum(); int pageSize = (pageInfo.getPageSize() == 0)? 10 : pageInfo.getPageSize(); PageInfo<User> result = userService.selectAll(pageNum, pageSize); model.addAttribute("users", result.getList()); model.addAttribute("pageInfo", result); return "userlist"; } @RequestMapping("/userdelete") public String userdelete(int id){ userService.deleteByPrimaryKey(id); return "redirect:/userlist"; } @RequestMapping("/useredit") public String useredit(int id, Model model){ User user = userService.selectByPrimaryKey(id); model.addAttribute("user", user); return "useredit"; } @RequestMapping(value = "/userupdateoradd", method = RequestMethod.POST) public String userUpdateOrAdd(User user){ if(user.getId() == 0){ userService.insertSelective(user); } else { userService.updateByPrimaryKeySelective(user); } return "redirect:/userlist"; }}Copy the code

Page userlist. HTML

<! DOCTYPE HTML > < HTML XMLNS :th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8" /> <title> User Management </title> <link href="/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <div> <nav class="navbar navbar-default" role="navigation"> <div class="container-fluid"> <div> <ul class="nav navbar-nav" > <li><a Href = "/ userlist" management > user < / a > < / li > < li > < a href = "#" > books management < / a > < / li > < / ul > < / div > < / div > < / nav > < / div > < div > < / h2 > < h2 > user management <table width="100%" border="0" cellpadding="0" cellpadding="0" class="table_list"> <thead> <tr> <th width="20%"> number </th> User name < th width = "20%" > < / th > < th width = "20%" > email < / th > < th width = "20%" > cell phone < / th > < th width = "20%" > action < / th > < / tr > < thead > <tbody> <tr th:each="user:${users}"> <td height="40px"><a th:text="${user.id}" data-toggle="modal" data-target="#myModal" onclick="values(this)"></a></td> <td th:text="${user.username}"></td> <td th:text="${user.email}"></td> <td th:text="${user.mobile}"></td> <td><a href="#" class="delete_a" Th: value = "${user. Id}" > delete < / a > < / td > < / tr > < / tbody > < / table > < / div > < / div > < script SRC = "/ js/jquery - 2.2.1. Min. Js" > < / script > <script src="/js/bootstrap.min.js"></script> </body> </html>Copy the code

8. Annotate scan on ZbookApplication

@ComponentScan(basePackages = {"com.zb"})
@MapperScan("com.zb.mapper")
Copy the code

9, add pagination incidentally (dependency package already added)

The service layer

    @Override
    public PageInfo<User> selectAll(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<User> users = userDao.selectAll();
        PageInfo<User> pageInfo = new PageInfo<>(users);
        return pageInfo;
    }
Copy the code

The controller layer

public String getUserList(Model model, PageInfo pageInfo){
        int pageNum  = (pageInfo.getPageNum() == 0)? 1 : pageInfo.getPageNum();
        int pageSize  = (pageInfo.getPageSize() == 0)? 10 : pageInfo.getPageSize();
        PageInfo<User> result = userService.selectAll(pageNum, pageSize);
        model.addAttribute("users", result.getList());
        model.addAttribute("pageInfo", result);
        return "userlist";
    }
Copy the code

Page modification:

<div id="example" style="text-align: center"> <ul id="pageLimit"></ul> </div> <input type="hidden" id="pageNum" name="pageNum" th:value="${pageInfo.pageNum}"  /> <input type="hidden" id="pages" name="pages" th:value="${pageInfo.pages}" />Copy the code
<script src="/js/bootstrap-paginator.min.js"></script> <script> $('#pageLimit').bootstrapPaginator({ currentPage: $("#pageNum").val(), totalPages: $("#pages").val(), size: "normal", bootstrapMajorVersion: 3, alignment: "Right ", numberOfPages: 5, itemTexts: function (type, page, current) {switch (type) {case "first": return" home "; Case "prev": return "previous "; Case "next": return "next"; Case "last": return "last"; case "page": return page; }}, onPageClicked: function (event, originalEvent, type, Page){// Bind an event to each header, where the page variable is the number of the page currently clicked. window.location.href = "userlist? pageNum=" + page; }}); $(function(){ $(".delete_a").click(function(){ var userId=$(this).attr("value"); If (confirm(" Do you want to delete? )){ window.location.href="/userdelete? id=" + userId; return ; }}); }); </script>Copy the code

This directory

At this time to restart, enter http://localhost:8080/userlist will see user list, also can be paged.

5. Simple login is realized by filter

1.

package com.zb.filter; import com.zb.model.User; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; @WebFilter(filterName = "sessionFilter",urlPatterns = {"/*"}) public class SessionFilter implements Filter { String NO_LOGIN = "You have not logged in "; String[] includeUrls = new String[]{"/login","/login_in"}; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; HttpServletResponse response = (HttpServletResponse)servletResponse; HttpSession session = request.getSession(); String url = request.getRequestURI(); boolean needFilter = isNeedFilter(url); Release the if / / static resources (url. EndsWith (" CSS ") | | url. The endsWith (" js ") | | url. The endsWith (" JPG ") ||url.endsWith(".gif")||url.endsWith(".png")){ filterChain.doFilter(servletRequest, servletResponse); return; } if(! needFilter){ filterChain.doFilter(servletRequest, servletResponse); } else { User user = (User)session.getAttribute(session.getId()); if(user ! = null){ filterChain.doFilter(servletRequest, servletResponse); } else { String requestType = request.getHeader("X-Requested-With"); If (requestType! =null && "XMLHttpRequest".equals(requestType)){ response.getWriter().write(this.NO_LOGIN); Response.sendredirect (request.getContextPath()+"/login"); response.sendreDirect (request.getContextPath()+"/login") } return; } } } public boolean isNeedFilter(String uri) { for (String includeUrl : includeUrls) { if(includeUrl.equals(uri)) { return false; } } return true; } @Override public void destroy() { } }Copy the code

2. Annotate ZbookApplication

@ServletComponentScan
Copy the code

3. Write the login logic in LoginController

package com.zb.controller; import com.zb.model.User; import com.zb.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @Controller public class LoginController { @Autowired private UserService userService; @RequestMapping("/login") public String login(){ return "login"; } @RequestMapping(value = "/login_in", method = RequestMethod.POST) public String login_in(User user, HttpServletRequest request, Model model){ User user1 = userService.validateUser(user.getUsername(), user.getPassword()); if(user1 == null){ return "login"; } HttpSession session = request.getSession(); session.setAttribute(session.getId(), user1); return "redirect:/userlist"; } @RequestMapping("/logout") public String logout(HttpServletRequest request){ request.getSession().removeAttribute(request.getSession().getId()); return "login"; }}Copy the code

Now you can simply log in

4. Modify the page to display the user name and exit

<div> <a href="logout" style="display: inline-block; </a> <p th:text="${# httpsession.getAttribute (# httpsession.getid ()). Username}" style="display: inline-block; float: right"></p> <p style="display: inline-block; Float: right"> </p> </div>Copy the code

Six, permissions,

Permission management we use now more popular Shiro, principle does not say, directly say how to use

1. Add dependency packages

<! -- Shiro permission --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> < version > 1. < / version > < / dependency > < the dependency > < groupId >. Org. Apache shiro < / groupId > < artifactId > shiro - web < / artifactId > < version > 1. < / version > < / dependency > < the dependency > < groupId > org, apache shiro < / groupId > < artifactId > shiro - spring < / artifactId > < version > 1. < / version > < / dependency > <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> The < version > 2.0.0 < / version > < / dependency >Copy the code

2, build table

Shiro needs 5 tables: user, role, permission, user role association table, role permission association table The user table has been established, now create 4 more tables

CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `rolename` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  `create_time` DATE DEFAULT NULL,
  `update_time` DATE DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `permissionname` varchar(255) DEFAULT NULL,
  `resourceType` varchar(255) DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  `permission` varchar(255) DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  `create_time` DATE DEFAULT NULL,
  `update_time` DATE DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `user_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL,
  `role_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

CREATE TABLE `role_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` varchar(255) DEFAULT NULL,
  `permission_id` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Copy the code
Insert into 'role' (id, rolename, description, status, create_time, update_time) VALUES (1, 'admin', 'admin', 'use', '2018-08-10', '2018-08-10'); Insert into 'role' (id, rolename, description, status, create_time, update_time) VALUES (2, 'manage', 'manager ', 'use', '2018-08-10', '2018-08-10'); Insert into 'role' (id, rolename, description, status, create_time, update_time) VALUES (3, 'user', 'user', 'use', '2018-08-10', '2018-08-10'); INSERT INTO `permission` (id, permissionname, resourceType, url, permission, status, create_time, Update_time) VALUES (1, 'user management' and 'menu', 'the userlist', 'user: list', 'use', '2018-08-10', '2018-08-10'); INSERT INTO `permission` (id, permissionname, resourceType, url, permission, status, create_time, Update_time) VALUES (2, 'the user to change', 'menu', 'useredit', 'user: edit', 'use', '2018-08-10', '2018-08-10'); INSERT INTO `permission` (id, permissionname, resourceType, url, permission, status, create_time, Update_time) VALUES (3, 'users delete', 'menu', 'userdelete', 'user: delete', 'use', '2018-08-10', '2018-08-10'); INSERT INTO `user_role` (id, user_id, role_id) VALUES (1, 1 ,1); INSERT INTO `user_role` (id, user_id, role_id) VALUES (2, 1 ,2); INSERT INTO `user_role` (id, user_id, role_id) VALUES (3, 1 ,3); INSERT INTO `user_role` (id, user_id, role_id) VALUES (4, 2 ,2); INSERT INTO `user_role` (id, user_id, role_id) VALUES (5, 3 ,3); INSERT INTO `user_role` (id, user_id, role_id) VALUES (6, 4 ,3); INSERT INTO `role_permission` (id, role_id, permission_id) VALUES (1, 1, 1); INSERT INTO `role_permission` (id, role_id, permission_id) VALUES (2, 1, 2); INSERT INTO `role_permission` (id, role_id, permission_id) VALUES (3, 1, 3); INSERT INTO `role_permission` (id, role_id, permission_id) VALUES (4, 2, 1); INSERT INTO `role_permission` (id, role_id, permission_id) VALUES (5, 2, 2); INSERT INTO `role_permission` (id, role_id, permission_id) VALUES (6, 3, 1);Copy the code

Load the bean

package com.zb.shiro; import java.util.LinkedHashMap; import java.util.Map; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.filter.DelegatingFilterProxy; /** * Shiro core is implemented via Filter, just as SpringMvc is DispachServlet to override. Since the Filter is used, we can generally guess that the URL rules are used to Filter and verify permissions, so we need to define a series of rules and access permissions about URL. */ @Configuration public class ShiroConfiguration { private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class); @Bean public FilterRegistrationBean delegatingFilterProxy(){ FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); DelegatingFilterProxy proxy = new DelegatingFilterProxy(); proxy.setTargetFilterLifecycle(true); proxy.setTargetBeanName("shiroFilter"); filterRegistrationBean.setFilter(proxy); return filterRegistrationBean; } /** * ShiroFilterFactoryBean handles the problem of intercepting resource files. Note that a single ShiroFilterFactoryBean configuration is or fails because it requires injection when the ShiroFilterFactoryBean is initialized: SecurityManager * Filter Chain Definition Description 1. A URL can be configured with multiple filters, separated by commas (,). 2. roles * */ @Bean("shiroFilter") public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager){ logger.info("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); / / must be set SecurityManager shiroFilterFactoryBean. SetSecurityManager (SecurityManager); Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); / / configuration exit filter, of which the specific exit code Shiro has achieved filterChainDefinitionMap for us. The put ("/logout ", "logout"); filterChainDefinitionMap.put("/*/*.js", "anon"); filterChainDefinitionMap.put("/*/*.css", "anon"); filterChainDefinitionMap.put("/login_in", "anon"); filterChainDefinitionMap.put("/login", "anon"); / / <! -- Filter chain definition, executed from top to bottom, usually with /** at the bottom --> this is a pit, if not careful code will not work; / / <! -- authc: All urls must be authenticated to be accessible; Anon: all the url can be anonymous access - > filterChainDefinitionMap. Put (" / * * ", "authc"); / / if you do not set the default automatically find under the root directory of the Web project "/ login JSP page shiroFilterFactoryBean. SetLoginUrl ("/login"); / / to jump after a successful login link shiroFilterFactoryBean setSuccessUrl ("/userlist "); // Unauthorised interface; shiroFilterFactoryBean.setUnauthorizedUrl("/login"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); return securityManager; } @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); return myShiroRealm; } /** * enable Shiro annotations (such as @requiresroles, @requirespermissions) with SpringAOP to scan classes that use Shiro annotations and perform security logic verification if necessary * Configuration under the two beans (DefaultAdvisorAutoProxyCreator and AuthorizationAttributeSourceAdvisor) this function can be realized * @ return * / @ bean public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } / open aop annotation support * * * * @ param securityManager * @ return * / @ Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } @Bean public ShiroDialect shiroDialect() { return new ShiroDialect(); }}Copy the code

4, write Realm

package com.zb.shiro; import com.zb.model.Permission; import com.zb.model.Role; import com.zb.model.User; import com.zb.service.UserService; 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.apache.shiro.util.ByteSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Resource; /** * Core class; * * @version v.0.1 */ public class MyShiroRealm extends AuthorizingRealm{private static Final Logger Logger = LoggerFactory.getLogger(MyShiroRealm.class); private static String SALT = "mySlalt"; @Resource private UserService userService; /** * Authentication information.(authentication) * : * Authentication is used to verify the user's identity * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { logger.info("MyShiroRealm.doGetAuthenticationInfo()"); // Get the user's input account. String username = (String)token.getPrincipal(); // Shiro can cache the User object according to the actual situation, if not, Shiro also has its own time interval mechanism. 2 minutes will not repeat this method User User = userService. SelectByUsername (username); logger.info("----->>userInfo=" + user.toString()); if(user == null){ return null; } /* * Get Permission from UserInfo,Role,Permission; * After fetching, all links can be displayed in the front for loop; */ //userInfo.setPermissions(userService.findPermissions(user)); userService.findRoleAndPermissions(user); // Determine the account; // Encryption mode; // Pass to AuthenticatingRealm for password matching using CredentialsMatcher, SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, // username user.getPassword(), // password bytesource.util.bytes (user.getusername () + SALT),// SALT =username+ SALT getName() //realm name); / / clear: If yes, save the user to the login authentication INFO, and do not need to do password comparison. // SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(// userInfo, // userinfo.getPassword (), // password // getName() //realm Name //); return authenticationInfo; } /** * This method is only called when hasRole,hasPermission is invoked. * 2. If the user exits abnormally, the cache will be cleared automatically; * 3. If we change the user's permission and the user does not exit the system, the modified permission will not take effect immediately. * (Manual programming is required to implement; Call a method in a realm that is already managed by Spring, so get a realm instance from Spring and call clearCached. * :Authorization is used to authorize users to perform operations, such as accessing a link or a resource file. * @param principals * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection Principals) {logger. The info (" permission configuration - > MyShiroRealm. DoGetAuthorizationInfo () "); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); User userInfo = (User)principals.getPrimaryPrincipal(); // Set the role information. // Support Set Set. / / corresponding all permissions for the user's Role (Role Role: the userInfo. GetRoleList ()) {authorizationInfo. AddRole (Role) getRolename ()); for(Permission p:role.getPermissionList()){ authorizationInfo.addStringPermission(p.getPermission()); } } return authorizationInfo; }}Copy the code

5, automatic generation of the four table code, plus the relevant

@Select("select * from Role where id in (select role_id from user_role where user_id = #{userId})")
List<Role> selectRoleByUserId(@Param("userId") int userId);
Copy the code
@Select("select * from permission where id in (select permission_id from role_permission where role_id = #{roleId})")
List<Permission> selectPermissionIdByRoleId(@Param("roleId") int roleId);
Copy the code

6. Modify the LoginController

Modifying login Methods

@RequestMapping(value = "/login_in", method = RequestMethod.POST) public String login_in(User user, HttpServletRequest request, Model model){ User user1 = userService.validateUser(user.getUsername(), user.getPassword()); if(user1 == null){ return "login"; } // (1) session // HttpSession session = request.getSession(); // session.setAttribute(session.getId(), user1); // return "redirect:/userlist"; // (3) shiro String msg ; UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); token.setRememberMe(true); Subject subject = SecurityUtils.getSubject(); try { subject.login(token); If (subjective.isauthenticated ()) {// Shiro's session and request's session encapsulate the same, // request.getSession().setAttribute(request.getSession().getid (),user); subject.getSession().setAttribute(subject.getSession().getId(),user); return "redirect:/userlist"; } else { return "login"; }} the catch (IncorrectCredentialsException e) {MSG = "login password mistake. Password for account " + token.getPrincipal() + " was incorrect."; model.addAttribute("message", msg); System.out.println(msg); } the catch (ExcessiveAttemptsException e) {MSG = "login failed too many"; model.addAttribute("message", msg); System.out.println(msg); } catch (LockedAccountException e) {MSG = "The account is locked. The account for username " + token.getPrincipal() + " was locked."; model.addAttribute("message", msg); System.out.println(msg); } catch (DisabledAccountException e) {MSG = "The account is disabled. The account for username " + token.getPrincipal() + " was disabled."; model.addAttribute("message", msg); System.out.println(msg); } the catch (ExpiredCredentialsException e) {MSG = "overdue account. The account for the username" + token. GetPrincipal () + "was expired."; model.addAttribute("message", msg); System.out.println(msg); } Catch (UnknownAccountException e) {MSG = "The account does not exist. There is no user with username of " + token.getPrincipal(); model.addAttribute("message", msg); System.out.println(msg); } catch (UnauthorizedException e) {MSG = "you are not authorized!" + e.getMessage(); model.addAttribute("message", msg); System.out.println(msg); } return "login"; } @RequestMapping("/logout") public String logout(HttpServletRequest request){ // request.getSession().removeAttribute(request.getSession().getId()); SecurityUtils.getSubject().getSession().removeAttribute(SecurityUtils.getSubject().getSession().getId()); return "login"; }Copy the code

7, modify the Contorller method, or add permissions to the page

@RequestMapping("/userlist")
@RequiresPermissions("user:list")
Copy the code
@RequestMapping("/userdelete")
@RequiresPermissions("user:delete")
Copy the code

This way or on the page

<shiro:hasPermission name="user:delete"></shiro:hasPermission>
Copy the code

At this point, permissions are added

Welcome to follow wechat official account: Fengji, reply: Springboot1, github address of the project.