1. 程式人生 > 實用技巧 >Spring Security 簡單瞭解與配置

Spring Security 簡單瞭解與配置

首先匯入依賴

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.37</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

在controller寫幾個測試介面

package com.yaimer.d;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @program: SpringSecurityTestProject
 * @description:
 * @author: yaimer
 * @create: 2020-09-05 01:04
 *
*/ @Controller public class inedx { @GetMapping("/log") @ResponseBody public String getHello(){ return "hello_阪井泉水"; } @GetMapping("/admin/log") @ResponseBody public String getAdminLog(){ return "hello_阪井泉水_admin_zard"; } @GetMapping("/user/log") @ResponseBody
public String getUserLog(){ return "hello_阪井泉水_user_zard"; } }

配置security 主要是自己寫一個@Configuration 配置登入頁,設定角色等資訊,也可在配置檔案properties或者yml中設定登入角色,會被Configuration中覆蓋

server.port=8081

#spring security user
spring.security.user.name=yaimer
spring.security.user.password=admin
spring.security.user.roles=admin

#spring security  connection
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql:///bytest?useUnicode=true&characterEncoding=utf-8

#rabbitmq
package com.yaimer.d;

import ch.qos.logback.core.net.ObjectWriter;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.provisioning.JdbcUserDetailsManager;

import javax.sql.DataSource;
import java.io.PrintWriter;

/**
 * @program: SpringSecurityTestProject
 * @description: 第二種security
 * @author: yaimer
 * @create: 2020-09-05 01:31
 **/
@Configuration
public class securityConfig extends WebSecurityConfigurerAdapter {

    /*
    * 加密
    * */
    @Bean
    PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    /*
    * 設定角色,會覆蓋properties
    * */
    /*@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("zard")
                .password("admin")
                .roles("admin")
                .and()
                .withUser("pzy")
                .password("123")
                .roles("user")
        ;
    }*/

    /**
     * 設定角色
     * @return
     */
    @Autowired
    DataSource dataSource;

    @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        //每次執行建立使用者
        /*InMemoryUserDetailsManager manager= new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("zard").password("admin").roles("admin").build());
        manager.createUser(User.withUsername("pzy").password("123").roles("user").build());*/

        //idea 快捷鍵alt+ins 搜尋 users.dll 複製語句建表

        JdbcUserDetailsManager  manager =  new JdbcUserDetailsManager(dataSource);
        if (!manager.userExists("zard")){
            manager.createUser(User.withUsername("zard").password("admin").roles("admin").build());
        }
        if (!manager.userExists("pzy")){
            manager.createUser(User.withUsername("pzy").password("123").roles("user").build());
        }
        return manager;
    }

    /**
     * 繼承角色許可權
     * @param http
     * @throws Exception
     */
    @Bean
    RoleHierarchy roleHierarchy(){
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        roleHierarchy.setHierarchy("ROLE_admin > ROLE_user");
        return roleHierarchy;
    }

    /*配置登入頁*/
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/Login.html")
                .loginProcessingUrl("/dol")
               /* .usernameParameter("name")
                .passwordParameter("pass")*/
                .successHandler((request, response, authentication) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(new ObjectMapper().writeValueAsString(authentication.getPrincipal()));
                    System.out.println(new ObjectMapper().writeValueAsString(authentication.getPrincipal()));
                    out.flush();
                    out.close();
                })
                .failureHandler((request, response, exception) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(new ObjectMapper().writeValueAsString(exception.getMessage()));
                    System.out.println(new ObjectMapper().writeValueAsString(exception.getMessage()));
                    out.flush();
                    out.close();
                })

                /*.defaultSuccessUrl("/log",true)*/
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler((request, response, authentication) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(new ObjectMapper().writeValueAsString("登出成功"));
                    out.flush();
                    out.close();
                })
                .permitAll()
                .and()
                .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(new ObjectMapper().writeValueAsString("沒有登入喲"));
                    out.flush();
                    out.close();
                })
        ;
    }

    /*過濾靜態資源*/

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**","/css/**","/img/**");
    }
}

然後就可以執行主程式,在位址列輸入頁面,需要登陸後訪問

登陸zard可以訪問/admin和/user下面的請求,登陸pzy則只能訪問/user下面的請求,logout可退出登陸