SpringBoot+SpringSecurity+mysql 登录
一、创建数据库表
DROP TABLE IF EXISTS `vhr`.`user`; CREATE TABLE `vhr`.`user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(45) NOT NULL DEFAULT '' COMMENT '登录用户名', `password` varchar(255) NOT NULL DEFAULT '' COMMENT '登录密码', `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否可用', `accountNonLocked` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户是否解锁状态', `name` varchar(32) DEFAULT NULL COMMENT '姓名', `userface` varchar(255) DEFAULT NULL COMMENT '用户头像', `phone` varchar(11) DEFAULT NULL COMMENT '手机号码', `telephone` varchar(16) DEFAULT NULL COMMENT '固定电话', `address` varchar(255) DEFAULT NULL COMMENT '联系地址', `email` varchar(255) DEFAULT NULL COMMENT '电子邮箱', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `accountNonExpired` tinyint(1) NOT NULL DEFAULT '1' COMMENT '账户是否未过期', `credentialsNonExpired` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户的凭据(密码)是否未过期', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`role`; CREATE TABLE `vhr`.`role` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `nameEn` varchar(45) NOT NULL DEFAULT '', `nameCn` varchar(45) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`user_role`; CREATE TABLE `vhr`.`user_role` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `uid` int(10) unsigned NOT NULL DEFAULT '0', `rid` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `FK_user_role_1` (`uid`), KEY `FK_user_role_2` (`rid`), CONSTRAINT `FK_user_role_1` FOREIGN KEY (`uid`) REFERENCES `user` (`id`), CONSTRAINT `FK_user_role_2` FOREIGN KEY (`rid`) REFERENCES `role` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`menu`; CREATE TABLE `vhr`.`menu` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `url` varchar(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '请求路径规则', `path` varchar(64) DEFAULT NULL COMMENT '路由path', `component` varchar(64) DEFAULT NULL COMMENT '组件英文名称', `name` varchar(64) DEFAULT NULL COMMENT '组件中文名称', `iconCls` varchar(64) DEFAULT NULL COMMENT '菜单图标', `keepAlive` tinyint(1) NOT NULL DEFAULT '0' COMMENT '菜单切换时是否保活', `requireAuth` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否登录后才能访问', `pid` int(10) unsigned DEFAULT NULL COMMENT '父菜单Id', `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否可用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `vhr`.`menu_role`; CREATE TABLE `vhr`.`menu_role` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `mid` int(10) unsigned NOT NULL DEFAULT '0', `rid` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `FK_menu_role_1` (`mid`), KEY `FK_menu_role_2` (`rid`), CONSTRAINT `FK_menu_role_1` FOREIGN KEY (`mid`) REFERENCES `menu` (`id`), CONSTRAINT `FK_menu_role_2` FOREIGN KEY (`rid`) REFERENCES `role` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
二、写一个测试类,手动生成加密后的密码,手动添加admin用户到用户表
package com.example.demo; import org.junit.Test; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; public class TestEncoder { @Test public void encoder() { String password = "admin"; BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(10); String enPassword = encoder.encode(password); System.out.println(enPassword); } }
三、后端代码
package com.example.pojo; import java.io.Serializable; public class Role implements Serializable { private Integer id;// `id` int(10) unsigned NOT NULL AUTO_INCREMENT, private String nameEn;// `nameEn` varchar(45) NOT NULL DEFAULT '', private String nameCn;// `nameCn` varchar(45) NOT NULL DEFAULT '', public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getNameEn() { return nameEn; } public void setNameEn(String nameEn) { this.nameEn = nameEn; } public String getNameCn() { return nameCn; } public void setNameCn(String nameCn) { this.nameCn = nameCn; } }
package com.example.pojo; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class User implements UserDetails,Serializable { private Integer id; // `id` int(10) unsigned NOT NULL AUTO_INCREMENT, private String username; // `username` varchar(45) NOT NULL DEFAULT '' COMMENT '登录用户名', private String password;// `password` varchar(255) NOT NULL DEFAULT '' COMMENT '登录密码', private Boolean enabled; // `enabled` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否可用', private Boolean accountNonLocked;// `accountNonLocked` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户是否解锁状态', private String name;// `name` varchar(32) DEFAULT NULL COMMENT '姓名', private String userface;// `userface` varchar(255) DEFAULT NULL COMMENT '用户头像', private String phone;// `phone` varchar(11) DEFAULT NULL COMMENT '手机号码', private String telepone;// `telephone` varchar(16) DEFAULT NULL COMMENT '固定电话', private String address;// `address` varchar(255) DEFAULT NULL COMMENT '联系地址', private String email;// `email` varchar(255) DEFAULT NULL COMMENT '电子邮箱', private String remark;// `remark` varchar(255) DEFAULT NULL COMMENT '备注', private Boolean accountNonExpired; // `accountNonExpired` tinyint(1) NOT NULL DEFAULT '1' COMMENT '账户是否未过期', private Boolean credentialsNonExpired;// `credentialsNonExpired` tinyint(1) NOT NULL DEFAULT '1' COMMENT '用户的凭据(密码)是否未过期', private List<Role> roles; @Override public Collection<? extends GrantedAuthority> getAuthorities() { List<SimpleGrantedAuthority> authorities = new ArrayList<>(); for(Role role : roles){ authorities.add(new SimpleGrantedAuthority(role.getNameEn())); } return authorities; } @Override public boolean isAccountNonExpired() { return accountNonLocked; } @Override public boolean isAccountNonLocked() { return accountNonExpired; } @Override public boolean isCredentialsNonExpired() { return credentialsNonExpired; } @Override public boolean isEnabled() { return enabled; } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public Boolean getEnabled() { return enabled; } public void setEnabled(Boolean enabled) { this.enabled = enabled; } public Boolean getAccountNonLocked() { return accountNonLocked; } public void setAccountNonLocked(Boolean accountNonLocked) { this.accountNonLocked = accountNonLocked; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUserface() { return userface; } public void setUserface(String userface) { this.userface = userface; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getTelepone() { return telepone; } public void setTelepone(String telepone) { this.telepone = telepone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } public Boolean getAccountNonExpired() { return accountNonExpired; } public void setAccountNonExpired(Boolean accountNonExpired) { this.accountNonExpired = accountNonExpired; } public Boolean getCredentialsNonExpired() { return credentialsNonExpired; } public void setCredentialsNonExpired(Boolean credentialsNonExpired) { this.credentialsNonExpired = credentialsNonExpired; } public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } }
package com.example.mapper; import com.example.pojo.Role; import com.example.pojo.User; import java.util.List; public interface UserMapper { User loadUserByUsername(String username); List<Role> getUserRolesByUid(Integer id); }
UserMapper.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.example.mapper.UserMapper"> <select id="loadUserByUsername" parameterType="String" resultType="com.example.pojo.User"> select * from user where username=#{username} </select> <select id="getUserRolesByUid" parameterType="int" resultType="com.example.pojo.Role"> select * from role r,user_role ur where r.id=ur.rid and ur.uid=#{id} </select> </mapper>
package com.example.security; import com.example.mapper.UserMapper; import com.example.pojo.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.ArrayList; import java.util.Collection; //@Component @Service public class DemoUserDetailsService implements UserDetailsService { private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfigurerAdapter.class); @Resource private PasswordEncoder passwordEncoder; // @Autowired @Resource private UserMapper userMapper; // @Override // public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // //根据用户名查找用户信息(通过Mapper查询用户信息) // logger.info("============loadUserByUsername========================="+username); // //根据查找到的用户信息判断用户是否被冻结 //// return new User(username,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));//authorities:权限 // return new User(username,passwordEncoder.encode("123456"), // true,true,true,true, // AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));//authorities:权限 // } // 重写loadUserByUsername 方法获得 userdetails 类型用户 @Override public UserDetails loadUserByUsername(String username) { User user = userMapper.loadUserByUsername(username); if (user != null) { user.setRoles(userMapper.getUserRolesByUid(user.getId())); return user; } else { throw new UsernameNotFoundException("admin: " + username + " do not exist!"); } } // public SecurityUser(User user) { // if (user != null) { // this.setUserUuid(user.getUserUuid()); // this.setUsername(user.getUsername()); // this.setPassword(user.getPassword()); // this.setEmail(user.getEmail()); // this.setTelephone(user.getTelephone()); // this.setRole(user.getRole()); // this.setImage(user.getImage()); // this.setLastIp(user.getLastIp()); // this.setLastTime(user.getLastTime()); // } // } // @Override // public Collection<? extends GrantedAuthority> getAuthorities() { // Collection<GrantedAuthority> authorities = new ArrayList<>(); // String username = this.getUsername(); // if (username != null) { // SimpleGrantedAuthority authority = new SimpleGrantedAuthority(username); // authorities.add(authority); // } // return authorities; // } // //账户是否未过期,过期无法验证 // @Override // public boolean isAccountNonExpired() { // return true; // } // // //指定用户是否解锁,锁定的用户无法进行身份验证 // @Override // public boolean isAccountNonLocked() { // return true; // } // // //指示是否已过期的用户的凭据(密码),过期的凭据防止认证 // @Override // public boolean isCredentialsNonExpired() { // return true; // } // // //是否可用 ,禁用的用户不能身份验证 // @Override // public boolean isEnabled() { // return true; // } }
package com.example.security; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; @Service public class DemoAccessDeniedHandler implements AccessDeniedHandler { private static final Logger logger = LoggerFactory.getLogger(DemoAccessDeniedHandler.class); @Resource private ObjectMapper objectMapper; @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { String name = SecurityContextHolder.getContext().getAuthentication().getName(); String requestUri = request.getRequestURI(); StringBuffer requestUrl = request.getRequestURL(); logger.info("用户[" + name + "]访问" + requestUri + "," + requestUrl + "失败,原因:权限不足!"); HashMap<String, String> map = new HashMap<>(16); map.put("code", "40300"); map.put("message", "权限不足"); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(map)); } }
package com.example.security; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.annotation.Resource; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration @EnableWebSecurity public class DemoSecurityConfig extends WebSecurityConfigurerAdapter { private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfigurerAdapter.class); @Autowired DemoUserDetailsService demoUserDetailsService; @Bean public PasswordEncoder passwordEncoder(){ // return NoOpPasswordEncoder.getInstance(); return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // auth.userDetailsService(userService); auth.userDetailsService(demoUserDetailsService); } @Override protected void configure(HttpSecurity http) throws Exception { logger.info("==============configure=================================="); // super.configure(http); http.csrf().disable(); http.authorizeRequests() //对请求进行授权 // .antMatchers("/login").permitAll() .antMatchers("/admin/**").hasRole("admin") .antMatchers("/db/**").hasRole("dba") .antMatchers("/user/**").hasRole("user") .anyRequest() //任何请求 .authenticated()//都要进行身份认证 .and() .formLogin()//表单登录 .loginPage("/login")//登录页面 // .loginProcessingUrl("/login") .permitAll();//和登录相关的接口都不需要认证即可访问 // http.authorizeRequests(). // antMatchers("/static/**").permitAll().anyRequest().authenticated(). // and().formLogin().loginPage("/login").permitAll().successHandler(loginSuccessHandler()). // and().logout().permitAll().invalidateHttpSession(true). // deleteCookies("JSESSIONID").logoutSuccessHandler(logoutSuccessHandler()). // and().sessionManagement().maximumSessions(10).expiredUrl("/login"); } //====================================================================== /** * 配置忽略的静态文件,不加的话,登录之前页面的css,js不能正常使用,得登录之后才能正常. */ @Override public void configure(WebSecurity web) throws Exception { // 忽略URL web.ignoring().antMatchers("/**/*.js", "/lang/*.json", "/**/*.css", "/**/*.js", "/**/*.map", "/**/*.html", "/**/*.png"); } @Bean public LogoutSuccessHandler logoutSuccessHandler() { //登出处理 return new LogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { } // @Override // public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { // try { // SecurityUser user = (SecurityUser) authentication.getPrincipal(); //// logger.info("USER : " + user.getUsername() + " LOGOUT SUCCESS ! "); // } catch (Exception e) { //// logger.info("LOGOUT EXCEPTION , e : " + e.getMessage()); // } // httpServletResponse.sendRedirect("/login"); // } }; } @Bean public SavedRequestAwareAuthenticationSuccessHandler loginSuccessHandler() { //登入处理 return new SavedRequestAwareAuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { User userDetails = (User) authentication.getPrincipal(); logger.info("USER : " + userDetails.getUsername() + " LOGIN SUCCESS ! "); super.onAuthenticationSuccess(request, response, authentication); } }; } // @Bean // UserDetailsService demoUserDetailsService() { // return new DemoUserDetailsService(); // } @Bean public UserDetailsService userDetailsService() { //用户登录实现 // return new DemoUserDetailsService(); return new UserDetailsService() { // @Override // public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { // return null; // } // @Autowired // private UserRepository userRepository; @Resource private PasswordEncoder passwordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.info("=-======loadUserByUsername======-=-========d================"+username); // User user = userRepository.findByUsername(s); // if (user == null) throw new UsernameNotFoundException("Username " + s + " not found"); // return new SecurityUser(user); return new User(username,passwordEncoder.encode("123456"), true,true,true,true, AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); } }; } // @Autowired // public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { // auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder()); // auth.eraseCredentials(false); // } }
package com.example.controller; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; @Controller public class LoginController { @RequestMapping(value = "/login", method = RequestMethod.GET) public String login() { System.out.println("--------/login------------"); return "/login"; } @RequestMapping("/") public String root() { return "/index"; } // public User getUser() { //为了session从获取用户信息,可以配置如下 // User user = new User(); // SecurityContext ctx = SecurityContextHolder.getContext(); // Authentication auth = ctx.getAuthentication(); // if (auth.getPrincipal() instanceof UserDetails) user = (User) auth.getPrincipal(); // return user; // } public HttpServletRequest getRequest() { return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); } }
package com.example.demo; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; //@SpringBootApplication(scanBasePackages = {"com.example.controller","com.example.service"}) @SpringBootApplication(scanBasePackages = {"com.example"}) @MapperScan("com.example.mapper") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
四、配置文件和前端代码
application.properties
#是否开启缓存,开发时可设置为false,默认为true spring.thymeleaf.cache=false #检查模板是否存在,默认为true spring.thymeleaf.check-template=true #检查模板位置是否存在,默认为true spring.thymeleaf.check-template-location=true #模板文件编码,UTF-8 spring.thymeleaf.encoding=UTF-8 #模板文件位置 spring.thymeleaf.prefix=classpath:/templates #Content-Type配置 spring.thymeleaf.servlet.content-type=text/html #模板文件后缀 spring.thymeleaf.suffix=.html #启用MVC Thymeleaf视图分辨率 spring.thymeleaf.enabled=true #模板编码 spring.thymeleaf.mode=LEGACYHTML5 #链中模板解析器的顺序 #spring.thymeleaf.template-resolver-order=o #应该中解决方案中排除的视图名称的逗号分隔列表 #spring.thymeleaf.excluded-view-names= #root日志以 WARN 级别输出 (日志只输出 WARN 及以上级别的信息) #logging.level.root=WARN #springframework.web 日志只以 DEBUG 级别输出 #logging.level.org.springframework.web=DEBUG #hibernate 日志以 ERROR 级别输出 #logging.level.org.hibernate=ERROR logging.file.name=e:\\log\\info.log logging.pattern.console=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n logging.pattern.file=%d{yyyy/MM/dd-HH:mm:ss} [%thread] %-5level %logger- %msg%n #数据源配置 spring.datasource.name=test spring.datasource.type=com.alibaba.druid.pool.DruidDataSource #加上?useUnicode=true&characterEncoding=UTF-8,否则可能插入数据库中文乱码 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/vhr?useUnicode=true&characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver #spring.datasource.sql-script-encoding=UTF-8 #spring.datasource.druid.filter.encoding.enabled=true spring.datasource.druid.filters=stat spring.datasource.druid.max-active=20 spring.datasource.druid.initial-size=1 spring.datasource.druid.max-wait=60000 spring.datasource.druid.min-idle=1 spring.datasource.druid.time-between-eviction-runs-millis=60000 spring.datasource.druid.min-evictable-idle-time-millis=300000 spring.datasource.druid.validation-query=select 'x' spring.datasource.druid.test-while-idle=true spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false spring.datasource.druid.pool-prepared-statements=true spring.datasource.druid.max-open-prepared-statements=20 #所有的mapper映射文件 #mybatis.mapper-locations=classpath*:com/springboot/mapper/*.xml #resource下的mapper映射文件 mybatis.mapper-locations=classpath*:mapper/**/*.xml #mybatis.mapper-locations=classpath:mapper/BookMapper.xml #mybatis.type-aliases-package= mybatis.config-location=classpath:mybatis/mybatis-config.xml pagehelper.helper-dialect=mysql pagehelper.reasonable=true pagehelper.support-methods-arguments=true pagehelper.params=count=countSql spring.session.store-type=none server.port=8060 #security.basic.enabled=false
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录</title> </head> <body> <h1>登录页面</h1> <form action="/login" method="post"> 用户名 : <input type="text" name="username"/> 密码 : <input type="password" name="password"/> <input type="submit" value="登录"> </form> </body> </html>