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

posted @ 2016-09-01 14:18  猪哥哥厉害  阅读(6640)  评论(0编辑  收藏  举报