1 主要目的
SpringBoot+SpringSecurity集成權限管理快速打造企業級聲明式安全認證授權解決方案之SpringBoot+SpringSecurity+mybatis+mysql
2 spring boot介紹
2.1 spring boot是什麼?
Spring Boot 是由 Pivotal 團隊提供的全新框架,其設計目的是用來簡化Spring應用的初始搭建以及開發過程。
Spring Boot可以輕鬆創建獨立的,生產級的基於Spring的應用程序。
2.2 spring boot解決了哪些問題?
spring boot 使編碼變的更簡單
spring boot 使配置變的更簡單
spring boot 使部署變的更簡單
。。。。
2.2.1 使編碼變的簡單
2.2.2 使得配置變的簡單
2.2.3 使得部署變的簡單
3 Spring Boot入門
3.1 Spring boot環境搭建
環境說明:Idea + maven+jdk1.8+mysql
搭建步驟:
一:瀏覽器輸入:start.spring.io
二:拷貝生成的項目,並使用Idea打開即可
3.2 Hello World
第一個:創建Controller
@Controller
public class HelloWorldController {
@RequestMapping("/hello")
@ResponseBody
public String showHelloWolrd(){
return "hello word";
}
}
第二個:運行main方法
第三個:瀏覽器輸入地址:http://localhost:8080/hello
項目結構如下:
總結:
1.創建一個maven工程,然後添加依賴即可(添加parent ,添加相關的啓動器,例如:添加web)
2.創建一個引導類(SpringBootAplication.class)
3.創建Controller即可。
4 Spring Boot的屬性配置
4.1 application.properties
默認的情況下,springboot 所有的屬性配置都在application.properties中進行配置,我們可以在裏面添加必要的屬性及對應的值,比如:默認的情況下 啓動項目,使用端口8080,可以設置端口爲其他。例如:
訪問時即可 使用8081.
其他的屬性配置,參考如下文檔:
https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
4.2 自定義屬性值及獲取
有時需要自定義配置屬性文件,設置值,並在代碼中使用它,可以在application.properties中設置。
例如:
定義值:
獲取值:
直接通過@value註解獲取即可。
4.3 java config獲取屬性值
由於如果屬性值比較多,一個一個通過@value註解的方式來獲取,比較繁瑣,可以通過java類進行映射,將屬性值映射到java類中,並交給spring管理,使用時直接注入即可,比較方便。
例如:
第一個:定義屬性:
第二個:定義映射屬性的類: 並設置getter和setter方法
@ConfigurationProperties(prefix = "mail")
@Component
public class MailPropertiesConfig {
private String host;
private String username;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
第三個:使用屬性文件中的值:直接注入即可。
5 mybatis的集成
在正式的項目中,需要將數據從數據庫中查詢出來展示到前臺相關的業務邏輯中。所有持久層的技術必不可少,這裏我們介紹現階段比較流行的持久層框架mybatis集成到springboot中。
5.1 mybatis集成的環境搭建
第一個:添加mybatis、mysql的依賴座標:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
第二個:創建數據庫實例,並配置連接信息
創建數據庫實例,並導入如上圖所示的sql。
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sbc
spring.datasource.username=root
spring.datasource.password=itcast
第三個:創建mapper(dao)接口
public interface UserMapper {
@Select(value = "select * from user where username=#{username}")
public User selectByUsername(String username);
}
第四個:掃描mapper接口所在的包,將由spring創建這些接口的代理對象
第五:測試,在test目錄下實現測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootApplicationTests {
@Autowired
private UserMapper mapper;
@Test
public void contextLoads() {
System.out.println(mapper.selectByUsername("zhangsan"));
}
}
測試OK
集成mybatis 總結:
1.添加mybaits的啓動器的依賴,
2.添加mysql的依賴
3.配置連接池的信息(application.properties配置連接數據庫的用戶名和密碼以及數據庫驅動,URL)
4.編寫mapper接口(相當於是Dao)
5.測試
5.2 頁面展示用戶相關信息
5.2.1 編寫service 接口及實現類
public interface UserService {
public User selectUserByUsername(String username);
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User selectUserByUsername(String username) {
return userMapper.selectByUsername(username);
}
}
結構如下圖:
5.2.2 編寫controller
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/user/info")
@ResponseBody
public User info(){
return userService.selectUserByUsername("zhangsan");
}
}
其他的CURD與此類似,此處不再討論。
6 spring security介紹
隨着互聯網的發展,當我們在淘寶或者京東上很方便的購物時,是否會想到我們的這種便利,如果不能保證我們的賬號安全的話,可想而知會出現什麼樣的後果。所以,系統的安全性顯得尤爲重要。當用戶購買下訂單時,系統必須要驗證此用戶的身份和相應的權限。而如果使用springmvc的攔截器,驗證過程顯得非常繁瑣。利用spring boot 和spring security將大大簡化我們的配置項和提高網站的安全性。
Spring Security是一個基於spring專注於爲Java應用程序提供身份驗證(Authentication)和授權(Authorization)的框架。同時在 Web 請求級和方法調用級處理身份確認和授權。
7 spring security入門
springsecurity 使用4.2.4.RELEASE版本。
第一個:添加依賴:
org.springframework.boot
spring-boot-starter-security
第二個:測試,訪問之前寫好的hello world
啓動項目 並在瀏覽器中輸入:http://localhost:8081/user/info
如圖:
默認的情況下:spring boot 和spring security已經集成 並攔截所有的請求,需要驗證通過才能放行。彈出框的方式 是默認的spring security的認證方式即(http basic的方式)
默認的情況下:用戶名爲user 密碼爲每次啓動項目是所生成的的隨機字符串,如圖:
8 表單登錄認證
正常的情況下,目前的驗證的方式不是我們想要的,更多的時候,需要有一個表單的登錄界面來進行用戶的身份確認(認證)。所以此時不能滿足我們的需要,我們修改成表單的方式來登錄。
第一個:創建配置類繼承WebSecurityConfigurerAdapter,進行配置。
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()//授權所有的請求 都需要通過認證才能訪問
.and()//並且
.formLogin();//採用表單提交的方式進行認證登錄
}
}
第二個:啓動項目,測試;輸入地址:http://localhost:8081/user/info
輸入用戶名和密碼即可。
9 自定義用戶認證
認證包括三個方面:第一個 獲取用戶的信息,第二個 校驗用戶 第三個 密碼加密
用戶的信息獲取主要使用mybatis獲取用戶信息,將獲取到的用戶的信息和頁面傳遞過來的用戶的信息進行匹配,如果成功,則放行,如果失敗,則返回錯誤的信息。匹配的過程是由spring security自己本身來實現的。
用戶的信息獲取需要通過實現一個接口:UserDetailsService 來實現這個功能。
@Component
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//從數據庫中獲取到用戶的信息
return new User(username,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
此時任何的用戶只要輸入了密碼爲123即可登錄成功。
因此需要從數據庫中查詢數據,並校驗數據的密碼是否正確
@Component
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//從數據庫中獲取到用戶的信息
com.itheima.springboot.pojo.User user = userService.selectUserByUsername(username);
if(user==null){
return null;//表示不存在
}
return new User(username,user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
此時如果還有其他的需求,比如:當用戶名和密碼都正確但是有時這個用戶已經被凍結了,此時也不能登錄成功,如果要實現這個需求,那麼需要對UserDetails接口說明一下。代碼需要重新構造:
@Component
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//從數據庫中獲取到用戶的信息
com.itheima.springboot.pojo.User user = userService.selectUserByUsername(username);
if(user==null){
return null;//表示不存在
}
//校驗用戶是否已經被凍結 用戶已經被凍結
boolean flagNonlock = false;//已經被凍結
// return new User(username,user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
return new User(username,user.getPassword(),true,true,true,flagNonlock, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
此時,用戶查詢的數據的數據是明文的,在企業開發中,密碼需要加密進行處理,不能以明文展示。此時需要加密。在spring security 中,處理加密的是一個passwordEncoder接口。
只需配置一個passwordEncoder接口的實現類即可。
首先配置passwordEncoder:
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder createPasswordEncoder(){
return new BCryptPasswordEncoder();
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()//授權所有的請求 都需要通過認證才能訪問
.and()//並且
.formLogin();//採用表單提交的方式進行認證登錄
}
}
修改校驗邏輯:
@Component
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//從數據庫中獲取到用戶的信息
com.itheima.springboot.pojo.User user = userService.selectUserByUsername(username);
if(user==null){
return null;//表示不存在
}
//進行加密;注意此處不應該這麼寫,此處的方法應當在用戶註冊的時候調用此方法進行加密處理,驗證身份時直接獲取數據庫中加過密的信息即可。
String encode = passwordEncoder.encode(user.getPassword());
System.out.println("密碼》》》"+encode);
//校驗用戶是否已經被凍結 用戶已經被凍結
// boolean flagNonlock = true;
return new User(username,encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
// return new User(username,encode,true,true,true,flagNonlock, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
自定義用戶認證
總結:
1.獲取用戶的信息的校驗(UserDetailsService)
2.處理用戶的校驗的業務邏輯處理(UserDetails)
3.密碼的加密(PasswordEncoder)—BCryptPasswordEncoder