springboot+mybatis+springsecurity初探算不算详解
最近在跟着某佬写项目,因为不是我搭架子,然后开始前告诉我说要用到springsecurity叫我先去看看,因为我还要准备高数的期中考试,于是就在写项目的途中边学边写,感觉真的是要多爽就有多爽。于是就去GitHub里面找了一个项目来学security框架,磕磕碰碰幸好还是走通了,话不多说,直接上干货。首先看看我的项目结构图,我感觉这个是关键然后是我的数据库设计河数据图,这个。一般重要吧...
最近在跟着某佬写项目,因为不是我搭架子,然后开始前告诉我说要用到springsecurity
叫我先去看看,因为我还要准备高数的期中考试,于是就在写项目的途中边学边写,
感觉真的是要多爽就有多爽。于是就去GitHub里面找了一个项目来学security框架,
磕磕碰碰幸好还是走通了,话不多说,直接上干货。
首先看看我的项目结构图,我感觉这个是关键
然后是我的数据库设计和数据库里面的数据的图,这个。一般重要吧。(ps:我用的sqlyog,感觉蛮好用的,安利一波)
数据库也没什么内容就三种权限
好了,该看的图都有了,那就开始干吧
首先是建立一个springboot项目,这个就不在这里说了,然后就是配置pom.xml了,要是不放心可以直接复制粘贴我的,已试毒。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot_mybatis_springsecurity_merge</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_mybatis_springsecurity_merge</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
接着是配置application.xml这里也可以直接复制我的。(ps:数据库记得该成自己的)
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/xxx
spring.datasource.username=root
spring.datasource.password=1234
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.mvc.view.suffix=.html
配完之后就可以开始写啦(PS:写之前或者最后去建立数据库都是可以的)
我是先写的实体类,因为实体类最好写,代码太长就不贴了(PS:最后会给GitHub的传送门,莫急)
然后就是写mapper,我这里直接用的注解,很短,可以贴上来看看
package com.example.demo.dao;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import com.example.demo.domain.SecurityUser;
@Mapper
@Repository
public interface SecurityUserMapper {
@Select("SELECT * FROM security_user WHERE username=#{username}")
SecurityUser findSecurityUserByUsername(String username);
}
好了,现在没用security框架之前我们能写的全部都写完了,接下来就是写security的部分了,刺激。
首先我们要写一个UserDetailsService的实现类,因为我们需要自定义的登录,(因为security本身会给一个登录的界面,显然我们不可能用哪个)
具体代码我贴上来,因为里面有注释就不多说了,看不懂的可以评论,一起讨论一起进步
package com.example.demo.service;
import java.util.ArrayList;
import java.util.Collection;
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.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.example.demo.dao.SecurityUserMapper;
import com.example.demo.domain.SecurityUser;
/**
* service注解是必须的,还要记得在配置类当中加载
* @author 11366
*
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private SecurityUserMapper dao;
//通过用户名得到用户信息并注册进去
//重写这个方法自己来实现登录验证
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SecurityUser suuser = dao.findSecurityUserByUsername(username);
if (suuser == null) {
System.out.println(username + "is not exist!");
throw new UsernameNotFoundException(username + "不存在");
}
UserDetails user = new User(username, suuser.getPassword(), true, true, true, true,
getAuthorities(suuser.getAccess_level()));
return user;
}
// 得到用户所拥有的权限
public Collection<GrantedAuthority> getAuthorities(int access){
Collection<GrantedAuthority> authorities = new ArrayList<>();
//首先所有的都拥有用户权限
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
//如果是0,那就是用户加管理员
if(access==0) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
//如果是2,那就是介于管理员和普通用户之间的权限,相当于可以理解为vip吧
if(access == 2) {
authorities.add(new SimpleGrantedAuthority("ROLE_TWO"));
}
return authorities;
}
}
写完之后就来到了最重要的部分,配置类了,之所以留到最好就是为了大家可以慢慢的接受,我反正是这样想的,之前的代码肯定没问题,那接下俩的肯定也没有问题。货不多说,上代码。
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
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.configuration.EnableWebSecurity;
/**
* 配置类,重写他的一些方法来设置一些web安全的细节如配置security的登录页面和传递参数,公共路径权限属性
*/
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.example.demo.service.PasswordEncoderImpl;
import com.example.demo.service.UserDetailsServiceImpl;
@Configuration
//请求控制权限到方法级别
@EnableGlobalMethodSecurity(securedEnabled = true)
//可以达到禁用默认登录界面
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//自定义认证对象
@Autowired
private UserDetailsServiceImpl serviceImpl;
//自定义登录规则就必须要重写这个方法
//身份验证管理生成器
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//不加.passwordEncoder(new PasswordEncoderImpl())
//就不是以明文的方式进行匹配,会报错
auth.userDetailsService(serviceImpl).passwordEncoder(new PasswordEncoderImpl());
}
//http请求安全处理
@Override
protected void configure(HttpSecurity http) throws Exception {
//请求权限配置
http.authorizeRequests()
.antMatchers("/","/login").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/login").defaultSuccessUrl("/hello").permitAll()
.and().logout().logoutSuccessUrl("/login").permitAll()
.and().exceptionHandling().accessDeniedPage("/denied");
//禁止使用默认的csrf
http.csrf().disable();
}
}
OK接下来验证的时刻了,也就是controller,在那里面我是直接用的@Secured注解,还有一种方式我没有用,因为考虑到这可能是入门,简单点更好。
package com.example.demo.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HelloController {
@RequestMapping("/hello")
@Secured("ROLE_USER")
public String hello() {
return "hello";
}
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/logout")
public String logout() {
return "home";
}
@RequestMapping("/denied")
public String denied() {
return "denied";
}
@RequestMapping("/admin")
@Secured("ROLE_ADMIN")
public String admin() {
return "admin";
}
}
好了,差不错就是这样了,等等,还有一个很重要的点,因为security框架并不是采用铭文传输,所以要么你数据库用md5加密,不过这样就麻烦了(也不麻烦其实但是考虑到入门嘛)于是我就直接用明文,用明文就需要实现PasswordEncoder接口啦,上代码
package com.example.demo.service;
/**
*
*/
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class PasswordEncoderImpl implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
// TODO Auto-generated method stub
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
// TODO Auto-generated method stub
return encodedPassword.equals(rawPassword.toString());
}
}
就是在配置security哪里加入,截图吧,有图有真相
OK,传送门明天再写吧。,顶不住了。回寝室啦
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)