您的位置:首页 > 编程语言 > Java开发

spring boot + mybatis + spring security(自定义登录界面)环境搭建

2017-12-03 22:11 781 查看

概述

在前不久用了spring boot、mybatis、spring security搭建了一个工程,中间经历了各种坑,最后得到一条经验:spring的文档很详细,入门最好以官方文档为准。这里讲的是以mav作为依赖管理工具

pom

搭建spring boot应用快捷的方式是在pom.xml中引入spring-boot-starter-parent 作为parent,如下:
<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/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.tw</groupId>
<artifactId>twboot</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>twboot Maven Webapp</name>
<url>http://maven.apache.org</url>

<properties>
<mybatis-spring-boot>1.2.0</mybatis-spring-boot>
</properties>

<!-- Spring Boot 启动父依赖 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>

<dependencies>
<!-- 模板引擎jar包, 已经包括了spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- Spring Boot Test 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!-- security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

<!-- 用于thymeleaf中使用security的标签 -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>

<!-- Spring Boot Mybatis 依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot}</version>
</dependency>

<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>

<!-- 上传组件包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>

</dependencies>

<build>
<finalName>twboot</finalName>
</build>
</project>

application.yml

spring boot 中默认会获取classpath下的application.yml或者application.propertis文件作为配置文件我用的前者
server:
port: 80
spring:
datasource:
username: xyz
password: xyz
driver-class-name: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@127.0.0.1:1521:XE
dbcp2:
max-idle: 10
validation-query: select 1 from dual

thymeleaf:
cache: false
prefix: classpath:/templates/
suffix: .html

mybatis:
type-aliases-package: com.tw.entity
mapper-locations:
- classpath:mapping/*.xml
上面的server.port 表示spring boot内置tomcat启动的端口是80,view层显示用的thymeleaf模板,模板前后缀也在配置文件中定义,这个和spring mvc那种配置类似;另工程中只用用一种view表示方式,用了thymeleaf就不要用jsp了,网上说的两种模板解析链是有先后处理顺序的,也就是说是有优先级;

Springboot启动类

在我们的package最顶层新建一个继承SpringBootServletInitializer的类(内容如下),这样一个spring boot项目就搭建好了
package com.tw;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;

@SpringBootApplication
@MapperScan("com.tw.dao")
public class StartApp extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(StartApp.class);
}

//添加Tomcat支持
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(StartApp.class);
}
}
上面的@SpringBootApplication 表面这是一个springboot应用,@MapperScan("com.tw.dao")  这个表示mybatis自动扫描dao接口的包名,这个包下的接口会自动和spring boot配置项mapper-locations中的mybatis sql配置文件映射

Controller

在spring boot中controller分为两类,一种是返回数据的Controller,一种是返回视图的Controller,分别注解是@RestController@Controller我这里写一个简单的controller
package com.tw.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;

import javax.servlet.ServletResponse;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class CommonController {

@PreAuthorize("hasRole('RRR')")
@RequestMapping(value={"/","/home"})
public String index() {
return "home/home";
}

@RequestMapping("/login")
public String login(Model model) {
System.out.println("to login----");
return "login/login";
}

@RequestMapping("/thymeleaf")
public String test(Map<String,Object> map,ServletResponse response) throws UnsupportedEncodingException, IOException{
map.put("name", "test");
System.out.println("thymeleaf----");
return "thymeleaf/hello2";
}

/**
* 功能描述:角色管理
* CHENY037 2017年11月29日
* @return
*/
@RequestMapping("/roleManage")
@PreAuthorize("hasRole('ROLE_MANAGE')")
public String roleManage(){
return "home/role";
}

}

spring security

自定义登录界面和自定义用户名密码校验配置类:
package com.tw.config.Security;

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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
* 配置类:
* 配置security的登录页面和传递的参数,公共路径权限属性等
*
* @author CHENY037
*
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UrlUserService urlUserService;

@Autowired
SessionRegistry sessionRegistry;

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll()
//                .antMatchers("/logout").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/bootstrap/**").permitAll()
.antMatchers("/fonts/**").permitAll()
.antMatchers("/favicon.ico").permitAll()
.anyRequest().authenticated()
//登录相关
.and().formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password").defaultSuccessUrl("/home")
.and().sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry)
.and().and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.and()
.httpBasic();
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
//这里是新增一个默认用户
auth.inMemoryAuthentication().withUser("huahua").password("hello").roles("ADMIN");
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(urlUserService).passwordEncoder(new PasswordEncoder() {

@Override
public String encode(CharSequence rawPassword) {
return (String)rawPassword;//MD5Util.encode((String) rawPassword);
}

@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
System.out.println(encodedPassword + "---" + (String)rawPassword);
return encodedPassword.equals((String) rawPassword);
}
});
}

@Bean
public SessionRegistry getSessionRegistry(){
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
}
自定义用户名密码校验类
package com.tw.config.Security;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.stereotype.Service;

import com.tw.dao.RoleDao;
import com.tw.dao.UserDao;
import com.tw.entity.role.TwRole;
import com.tw.entity.role.TwUser;

/**
* 自定义用户名密码校验实现
*
* @author CHANY037 2017-11
*
*/
@Service
public class UrlUserService implements UserDetailsService {

@Autowired
UserDao userDao;

@Autowired
RoleDao roleDao;

/**
* employeeId 用户工号,在数据库中保证存储唯一
*/
@Override
public UserDetails loadUserByUsername(String employeeId) { //重写loadUserByUsername 方法获得 userdetails 类型用户

TwUser user = userDao.findByEmployeeId(employeeId);

if(user == null){
throw new UsernameNotFoundException(employeeId + " do not exist!");
} else {
System.out.println(user.getPassword() + " --pw-- ");
List<TwRole> roles = roleDao.findRoleByEmployeeId(employeeId);
List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();

//写入用户的角色  ***  切记 由于框架原因 角色名称要以 ROLE_ 开头 **** 血泪史 ****
//源码:org.springframework.security.access.expression.SecurityExpressionRoot hasAnyRole()
for (TwRole role : roles) {
if (role != null && role.getRoleName() != null) {
SimpleGrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRoleCode());
grantedAuthorities.add(grantedAuthority);
}
}
org.springframework.security.core.userdetails.User uu = new User(employeeId, user.getPassword(), grantedAuthorities);
return uu;
}
}
}
登录界面html 即 上面
CommonController 里定义的login方法返回的视图
<!doctype html><html lang="en" class="no-js"xmlns="http://www.w3.org/1999/xhtml"xmlns:th="http://www.thymeleaf.org"xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"><head><meta charset="UTF-8"/><title>Login</title><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /><!--  thymeleaf 默认从resources 下的 static目录获取 --><link rel="stylesheet" th:href="@{bootstrap/css/bootstrap.min.css}"/><script th:src="@{js/jquery.min.js}"></script><script th:src="@{bootstrap/js/bootstrap.min.js}"></script><style>.form-control{width: 200px;}</style></head><body style="background: url(img/login.jpg);width: 98%;"><div style="margin-top: 150px;margin-left: 800px;margin-bottom: 160px;" ><form class="form-horizontal" method="post" th:action="@{/login}"><div class="form-group"><label for="inputEmail3" class="col-sm-2 control-label">用户名</label><div class="col-sm-10"><input autocomplete="off" type="text" class="form-control" name="username" /></div></div><div class="form-group"><label for="inputPassword3" class="col-sm-2 control-label">密码</label><div class="col-sm-10"><input type="text" class="form-control" name="password" onfocus="this.type='password'"/></div></div><div class="form-group"><div class="col-sm-offset-2 col-sm-10"><div class="checkbox"><label><input type="checkbox" />Remember me</label><!-- 功能暂未实现 --></div></div></div><div class="form-group"><div class="col-sm-offset-2 col-sm-10"><button type="submit" class="btn btn-default">登录</button></div></div></form></div><!-- 引入 页脚 --><div th:replace="common/footer :: footer"></div></body></html>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: