一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java中Spring Security的實例詳解

java中Spring Security的實例詳解

2020-12-26 15:01u011116672 Java教程

這篇文章主要介紹了java中Spring Security的實例詳解的相關資料,spring security是一個多方面的安全認證框架,提供了基于JavaEE規(guī)范的完整的安全認證解決方案,需要的朋友可以參考下

javaSpring Security的實例詳解

spring security是一個多方面的安全認證框架,提供了基于JavaEE規(guī)范的完整的安全認證解決方案。并且可以很好與目前主流的認證框架(如CAS,中央授權系統(tǒng))集成。使用spring security的初衷是解決不同用戶登錄不同應用程序的權限問題,說到權限包括兩部分:認證和授權。認證是告訴系統(tǒng)你是誰,授權是指知道你是誰后是否有權限訪問系統(tǒng)(授權后一般會在服務端創(chuàng)建一個token,之后用這個token進行后續(xù)行為的交互)。

spring security提供了多種認證模式,很多第三方的認證技術都可以很好集成:

  • Form-based authentication (用于簡單的用戶界面)
  • OpenID 認證
  • Authentication based on pre-established request headers (such as Computer - Associates Siteminder)根據(jù)預先建立的請求頭進行驗證
  • JA-SIG Central Authentication Service ( CAS, 一個開源的SSO系統(tǒng))
  • Java Authentication and Authorization Service (JAAS)

這里只列舉了部分,后面會重點介紹如何集成CAS,搭建自己的認證服務。

在spring boot項目中使用spring security很容易,這里介紹如何基于內存中的用戶和基于數(shù)據(jù)庫進行認證。

準備

pom依賴:

?
1
2
3
4
5
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
        <version>1.5.1.RELEASE</version>
      </dependency>

配置:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
  @Bean
  public UserDetailsService userDetailsService() {
    return new CustomUserDetailsService();
  }
 
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("rhwayfun").password("1209").roles("USERS")
        .and().withUser("admin").password("123456").roles("ADMIN");
    //auth.jdbcAuthentication().dataSource(securityDataSource);
    //auth.userDetailsService(userDetailsService());
  }
 
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()//配置安全策略
        //.antMatchers("/","/index").permitAll()//定義/請求不需要驗證
        .anyRequest().authenticated()//其余的所有請求都需要驗證
        .and()
        .formLogin()
        .loginPage("/login")
        .defaultSuccessUrl("/index")
        .permitAll()
        .and()
        .logout()
        .logoutSuccessUrl("/login")
        .permitAll();//定義logout不需要驗證
 
    http.csrf().disable();
  }
 
}

這里需要覆蓋WebSecurityConfigurerAdapter的兩個方法,分別定義什么請求需要什么權限,并且認證的用戶密碼分別是什么。

?
1
2
3
4
5
6
7
8
9
10
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
  /**
   * 統(tǒng)一注冊純RequestMapping跳轉View的Controller
   */
  @Override
  public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/login").setViewName("/login");
  }
}

添加登錄跳轉的URL,如果不加這個配置也會默認跳轉到/login下,所以這里還可以自定義登錄的請求路徑。

登錄頁面:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
 
<%--<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>--%>
 
<html>
<head>
  <meta charset="utf-8">
  <title>Welcome SpringBoot</title>
  <script src="/js/jquery-3.1.1.min.js"></script>
  <script src="/js/index.js"></script>
</head>
<body>
 
<form name="f" action="/login" method="post">
  <input id="name" name="username" type="text"/><br>
  <input id="password" name="password" type="password"><br>
  <input type="submit" value="login">
  <input name="_csrf" type="hidden" value="${_csrf}"/>
</form>
 
<p id="users">
 
</p>
 
<script>
  $(function () {
    $('[name=f]').focus()
  })
</script>
</body>
 
</html>

基于內存

SecurityConfig這個配置已經是基于了內存中的用戶進行認證的,

?
1
2
3
4
5
auth.inMemoryAuthentication()//基于內存進行認證
.withUser("rhwayfun").password("1209")//用戶名密碼
.roles("USERS")//USER角色
        .and()
        .withUser("admin").password("123456").roles("ADMIN");//ADMIN角色

訪問首頁會跳轉到登錄頁面這成功,使用配置的用戶登錄會跳轉到首頁。

基于數(shù)據(jù)庫

基于數(shù)據(jù)庫會復雜一些,不過原理是一致的只不過數(shù)據(jù)源從內存轉到了數(shù)據(jù)庫。從基于內存的例子我們大概知道spring security認證的過程:從內存查找username為輸入值得用戶,如果存在著驗證其角色時候匹配,比如普通用戶不能訪問admin頁面,這點可以在controller層使用@PreAuthorize("hasRole('ROLE_ADMIN')")實現(xiàn),表示只有admin角色的用戶才能訪問該頁面,spring security中角色的定義都是以ROLE_開頭,后面跟上具體的角色名稱。

如果要基于數(shù)據(jù)庫,可以直接指定數(shù)據(jù)源即可:

?
1
auth.jdbcAuthentication().dataSource(securityDataSource);

只不過數(shù)據(jù)庫標是spring默認的,包括三張表:users(用戶信息表)、authorities(用戶角色信息表)

以下是查詢用戶信息以及創(chuàng)建用戶角色的SQL(部分,詳細可到JdbcUserDetailsManager類查看):

?
1
2
3
4
5
public static final String DEF_CREATE_USER_SQL = "insert into users (username, password, enabled) values (?,?,?)";
 
public static final String DEF_INSERT_AUTHORITY_SQL = "insert into authorities (username, authority) values (?,?)";
 
public static final String DEF_USER_EXISTS_SQL = "select username from users where username = ?";

那么,如果要自定義數(shù)據(jù)庫表這需要配置如下,并且實現(xiàn)UserDetailsService接口:

?
1
2
3
4
5
6
auth.userDetailsService(userDetailsService());
 
@Bean
  public UserDetailsService userDetailsService() {
    return new CustomUserDetailsService();
  }

CustomUserDetailsService實現(xiàn)如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Service
public class CustomUserDetailsService implements UserDetailsService {
 
  /** Logger */
  private static Logger log = LoggerFactory.getLogger(CustomUserDetailsService.class);
 
  @Resource
  private UserRepository userRepository;
 
  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    if (StringUtils.isBlank(username)) {
      throw new IllegalArgumentException("username can't be null!");
    }
    User user;
    try {
      user = userRepository.findByUserName(username);
    } catch (Exception e) {
      log.error("讀取用戶信息異常,", e);
      return null;
    }
    if (user == null) {
      return null;
    }
    List<UserAuthority> roles = userRepository.findRoles(user.getUserId());
    List<SimpleGrantedAuthority> authorities = new ArrayList<>();
    for (UserAuthority role : roles) {
      SimpleGrantedAuthority authority = new SimpleGrantedAuthority(String.valueOf(role.getAuthId()));
      authorities.add(authority);
    }
    return new org.springframework.security.core.userdetails.User(username, "1234", authorities);
  }
 
 
}

我們需要實現(xiàn)loadUserByUsername方法,這里面其實級做了兩件事:查詢用戶信息并返回該用戶的角色信息。

數(shù)據(jù)庫設計如下:

java中Spring Security的實例詳解

數(shù)據(jù)庫設計

g_users:用戶基本信息表
g_authority:角色信息表
r_auth_user:用戶角色信息表,這里沒有使用外鍵約束。

使用mybatis generator生成mapper后,創(chuàng)建數(shù)據(jù)源SecurityDataSource。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@Configuration
@ConfigurationProperties(prefix = "security.datasource")
@MapperScan(basePackages = DataSourceConstants.MAPPER_SECURITY_PACKAGE, sqlSessionFactoryRef = "securitySqlSessionFactory")
public class SecurityDataSourceConfig {
 
  private String url;
 
  private String username;
 
  private String password;
 
  private String driverClassName;
 
  @Bean(name = "securityDataSource")
  public DataSource securityDataSource() {
    DruidDataSource dataSource = new DruidDataSource();
    dataSource.setDriverClassName(driverClassName);
    dataSource.setUrl(url);
    dataSource.setUsername(username);
    dataSource.setPassword(password);
    return dataSource;
  }
 
  @Bean(name = "securityTransactionManager")
  public DataSourceTransactionManager securityTransactionManager() {
    return new DataSourceTransactionManager(securityDataSource());
  }
 
  @Bean(name = "securitySqlSessionFactory")
  public SqlSessionFactory securitySqlSessionFactory(@Qualifier("securityDataSource") DataSource securityDataSource)
      throws Exception {
    final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
    sessionFactory.setDataSource(securityDataSource);
    sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
        .getResources(DataSourceConstants.MAPPER_SECURITY_LOCATION));
    return sessionFactory.getObject();
  }
 
  public String getUrl() {
    return url;
  }
 
  public void setUrl(String url) {
    this.url = url;
  }
 
  public String getUsername() {
    return username;
  }
 
  public void setUsername(String username) {
    this.username = username;
  }
 
  public String getPassword() {
    return password;
  }
 
  public void setPassword(String password) {
    this.password = password;
  }
 
  public String getDriverClassName() {
    return driverClassName;
  }
 
  public void setDriverClassName(String driverClassName) {
    this.driverClassName = driverClassName;
  }
}

那么DAO UserRepository就很好實現(xiàn)了:

?
1
2
3
4
5
6
7
public interface UserRepository{
 
  User findByUserName(String username);
 
  List<UserAuthority> findRoles(int userId);
 
}

在數(shù)據(jù)庫插入相關數(shù)據(jù),重啟項目。仍然訪問首頁跳轉到登錄頁后輸入數(shù)據(jù)庫插入的用戶信息,如果成功跳轉到首頁這說明認證成功。

如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

原文鏈接:http://blog.csdn.net/u011116672/article/details/77428049

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲高清在线视频 | chinese456老人gay| 色综合欧美色综合七久久 | 日韩欧美在线观看综合网另类 | 日韩国产欧美一区二区三区 | 国产原创一区二区 | 亚洲欧美另类综合 | 亚洲国产日韩欧美一区二区三区 | 久9视频这里只有精品123 | 91天堂在线 | 欧美另类bbbxxxxx另类 | 湿好紧太硬了我太爽了 | 欧美成年黄网站色高清视频 | 美女翘臀内疯狂进出 | 亚洲国产精品久久网午夜小说 | 久久强奷乱码老熟女 | 亚洲成人mv| 国产高清免费午夜在线视频 | 冰雪奇缘1完整版免费观看 变形金刚第一部 | 久久 这里只精品 免费 | 日本在线视频免费观看 | 国产久草在线 | 国产免费久久精品 | 9久re在线观看视频精品 | 国产一区二区精品久久 | 精品综合久久久久久88小说 | 欧美三级不卡在线观线看高清 | 日本四虎影视 | 国产免费福利片 | 四虎影院网站 | 国产一级毛片潘金莲的奶头 | 精品欧美一区二区精品久久 | 国内久久 | 国内交换一区二区三区 | 17岁韩国在线观看免费1 | 韩日视频在线观看 | 国产精品刺激好大好爽视频 | 日本www视频在线观看 | 久久黄色录像 | 99精品热视频 | 国产青草视频在线观看免费影院 |