springboot +spring security4 +thymeleaf 后台管理系統


 需求:一個后台管理系統,現在用的springboot 微框架比較多, 所以這里也使用了, 后台權限用 spring security ,之前以前覺得聽復雜 。 后來發現還是蠻簡單的, 看了源代碼之后。模板用的 thymeleaf, 以上是背景介紹。

   看看實現吧。

    1.核心類(安全類)

  

package com.ycmedia.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.method.configuration.EnableGlobalMethodSecurity;
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.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private YcAnthencationProder provider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //允許訪問靜態資源
        http.authorizeRequests()
                .antMatchers("/upload", "/css/**", "/js/**", "/images/**",
                        "/resources/**", "/lib/**", "/skin/**", "/template/**")
                .permitAll();
        //所有的訪問都需要權限驗證
        http.authorizeRequests().anyRequest().authenticated();
        //訪問失敗頁url
        http.formLogin().failureUrl("/login?error").
        //登錄信息保存
        successHandler(loginSuccessHandler()).
        //訪問成功頁url
        defaultSuccessUrl("/login")
        //默認訪問頁
                .loginPage("/login")
                .permitAll().and().logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                //注銷失敗跳轉到登錄頁面
                .logoutSuccessUrl("/login").permitAll();

        // 允許iframe 嵌套
        http.headers().frameOptions().disable();
        //關閉csrf 防止循環定向
        http.csrf().disable();
    }

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        //采用自定義驗證
        auth.authenticationProvider(provider);
        //需要采用加密
//        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }
    
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(4);
    }
    
    
    /**
     * 用戶或者管理員登錄日志
     */
    @Bean
    public LoginSuccessHandler loginSuccessHandler(){
        return new LoginSuccessHandler();
    }
    



}

======================這些配置其實很簡單, 很強大, 網上的例子很多。

 2、啟動類 ,因為比較懶

package com.ycmedia;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.ErrorPage;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.ycmedia.service.UserService;

@SpringBootApplication
@EnableAutoConfiguration
public class Application extends WebMvcConfigurerAdapter {

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserService();
    }
    /**
     * 自定義異常頁
     */
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {

       return (container -> {
            ErrorPage error401Page = new ErrorPage(HttpStatus.FORBIDDEN, "/403.html");
            ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404.html");
            ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500.html");
            container.addErrorPages(error401Page, error404Page, error500Page);
       });
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

 

 這個啟動類, 加載了 核心實現 userDetailService。

 

3、實現類重寫。

package com.ycmedia.service;

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

import javax.annotation.security.RolesAllowed;

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.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.stereotype.Service;

import com.ycmedia.dao.UserDao;
import com.ycmedia.entity.User;

@Service
public class UserService implements UserDetailsService {
    @Autowired
    private UserDao userDao;

    public List<User> loadAllUsers() {
        return userDao.loadAllUsers();
    }

    /**
     * 保存用戶
     * 
     * @param user
     */
    public void save(User user) {
     BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        if (user.getRole() == "0") {
            user.setRole("ROLE_ADMIN");
        } else {
            user.setRole("ROLE_USER");
        }
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userDao.insert(user);
    }

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        User user = userDao.findUserByName(username);
        if (user == null) {
            throw new UsernameNotFoundException(username + " not found");
        }
        System.err.println(user.getRole() + "正在執行查詢角色名稱");
        return new UserDetails() {
            private static final long serialVersionUID = 3720901165271071386L;
            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                List<SimpleGrantedAuthority> auths = new ArrayList<>();
                auths.add(new SimpleGrantedAuthority(user.getRole()));
                return auths;
            }

            @Override
            public String getPassword() {
                return user.getPassword();
            }

            @Override
            public String getUsername() {
                return username;
            }

            @Override
            public boolean isAccountNonExpired() {
                return true;
            }

            @Override
            public boolean isAccountNonLocked() {
                return true;
            }

            @Override
            public boolean isCredentialsNonExpired() {
                return true;
            }

            @Override
            public boolean isEnabled() {
                return true;
            }
        };
    }
    
    public User getUserByname(String username) {
        return userDao.findUserByName(username);
    }

}

spring security 會自動調用被重寫的 loaduserbyusername ,獲取  用戶所有的信息 存在    Authentication

4.看下controller  的實現, 是基於注解的,因為項目比較簡單。

/**tpl-add
     * 跳轉到編輯廣告
     * @return
     */
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN')")
    @RequestMapping(value = "/product-edit")
    public ModelAndView  toEditAd(@RequestParam("id")String id ,Creative creative){
        creative = adservice.findAdById(id);
        return new ModelAndView("product-add" ,"creative",creative );
    }
    
    /**
     * 
     * 跳轉到編輯廣告
     * @return
     */
    @PreAuthorize("hasAnyAuthority('ROLE_ADMIN')")
    @RequestMapping(value = "/tpl-add")
    public ModelAndView  toTplAdd(@ModelAttribute(value="tpl")CreativeTpl tpl){
        return new ModelAndView("tpl-add" );
    }

在方法 是作用注解, 普通用戶 沒有權限, 直接跳到403 頁面。

 

5、實體 User。 這個很簡單。

package com.ycmedia.entity;


public class User {

    private Integer id;
    private String username;
    private String password;
    private String role;

    private String realname;

    private String mobile;

    private Integer state;

    private String info;

    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 getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public String getRealname() {
        return realname;
    }

    public void setRealname(String realname) {
        this.realname = realname;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public Integer getState() {
        return state;
    }

    public void setState(Integer state) {
        this.state = state;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

}

7 。 表的話就用了一張。 user表

 

用戶對應的權限和用戶在一張表。

==========================================================================================================================================

看看源碼===========

 

 

 

 

==========================這里包括用戶名,密碼校驗等。

spring真的很強大

=======

 

附上 gitHup  完整項目地址:https://github.com/zhuliangxing823/quanming.git


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM