这几天由于需求,整合了一下Springsecurity的安全框架,独乐乐不如众乐乐和大家分享一下,避免不必要的坑。## 标题
这里奉上GitHub克隆地址点击https://github.com/xjjxltzf/CSDN.git
进入正题,本次将采用本人的理解讲解该安全框架的整合。
4.0.0
com.demo.SpringBootMyBatisSpringSecurity
SpringBootMyBatisSpringSecurity
0.0.1-SNAPSHOT
jar
SpringBootMyBatisSpringSecurity
SpringBootMyBatisSpringSecurity
org.springframework.boot
spring-boot-starter-parent
1.5.9.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-thymeleaf
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-security
org.thymeleaf.extras
thymeleaf-extras-springsecurity4
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.1
mysql
mysql-connector-java
5.1.32
org.projectlombok
lombok
junit
junit
org.springframework.security
spring-security-core
org.springframework.security
spring-security-web
org.springframework.security
spring-security-config
org.springframework.security
spring-security-taglibs
org.springframework.boot
spring-boot-maven-plugin
org.apache.maven.plugins
maven-compiler-plugin
3.1
true
true
${JAVA8_HOME}/bin/javac
整合采用yml+mybatis-config.xml进行配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql:///数据库名?serverTimezone=UTC
username: 你的数据库用户名
password: 你的数据库密码
mybatis:
#这里是Mybatis的配置文件映射路径
config-location: classpath:mybatis-config.xml
*---------------------------------------------------------配置搞定开始撸码-------------------------------------------------
国际惯例
com.demo.pojo
>DbUser.java
package com.demo.pojo;
import lombok.Data;
/*
* 测试用户对象
*/
@Data
public class DbUser {
private String username;//用户名
private String password;//用户密码
private Integer access_level;//用户权限标识
private String description;//用户权限描述
}
com.demo.dao
>DataMapper.java
package com.demo.dao;
import com.demo.pojo.DbUser;
/*
* Mybatis数据映射,
*/
public interface DataMapper {
DbUser getUserLoginInfo(String username);
}
>DataMapper.xml
com.demo.impl
这里开始写有关Springsecurity的代码,此实现层功能描述:调用DAO层通过用户输入的用户名查询用户记录返回用户信息
package com.demo.impl;
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.demo.dao.DataMapper;
import com.demo.pojo.DbUser;
/*
* 自定义用户名密码校验实现,一定要@Service注解,然后在配置类中加载(重载configure)
*/
@Service
public class UserDetailInfo implements UserDetailsService{
//数据库操作
@Autowired
private DataMapper dbDataMapper;
//必须重写,自己来实现登陆验证
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("这里点击登录后进");
System.out.println("user["+username+"] is logining...");
DbUser dbUser = dbDataMapper.getUserLoginInfo(username);
if(dbUser==null)
{
System.out.println("user["+username+"] is not exist!");
throw new UsernameNotFoundException(username + " do not exist!");
}
System.out.println("Get user info from db: "+ dbUser.toString());
UserDetails user = new User(dbUser.getUsername(), dbUser.getPassword(), true, true, true, true,
getAuthorities(dbUser.getAccess_level()));
return user;
}
/**
* 获得访问角色权限
*/
public Collection getAuthorities(Integer access) {
Collection authorities = new ArrayList<>();
//所有的用户默认拥有ROLE_USER权限
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
if (access.compareTo(0) == 0) {
// 如果参数access为0.则拥有ROLE_ADMIN权限
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}else if(access.compareTo(2) == 0) {
// 如果参数access为2.则拥有ROLE_TAO权限
authorities.add(new SimpleGrantedAuthority("ROLE_TAO"));
}
//最终这里返回的是用户权限集合
return authorities;
}
}
**
**
com.demo.config
>WebSecurityConfig.java
package com.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;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.demo.impl.UserDetailInfo;
/*
* 配置类:
* 重写它的方法来设置一些web安全的细节,如配置security的登录页面和传递的参数,公共路径权限属性等
*/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true) //控制权限到请求方法级别
//@EnableGlobalMethodSecurity(prePostEnabled = true)//方法调用前鉴权
@EnableWebSecurity //禁用Boot的默认Security配置,配合@Configuration启用自定义配置(需要扩展WebSecurityConfigurerAdapter)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//自定义认证对象
@Autowired
private UserDetailInfo urlUserService;
//HTTP请求安全处理
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("这里程序运行第二个进入");
//请求权限配置
http.authorizeRequests()
//指定了/和/home不需要任何认证就可以访问,
.antMatchers("/", "/login","/**").permitAll()
//任何请求,登录后方可访问。
.anyRequest().authenticated()
//登陆界面参数
.and().formLogin().loginPage("/login").defaultSuccessUrl("/hello")/*.usernameParameter("username").passwordParameter("password")*/.permitAll()
//设置注销成功后跳转页面,默认是跳转到登录页面
.and().logout().logoutSuccessUrl("/login").permitAll()
//权限访问失败界面,关键,如果不定义的话会抛出异常
.and().exceptionHandling().accessDeniedPage("/denied")
;
http.csrf().disable();
}
/*
* 身份验证管理生成器。一定要重载!!!不然自定义的登陆校验不生效
* */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("不用测试了这里程序运行第一个进入");
auth.userDetailsService(urlUserService)
/*.passwordEncoder(new PasswordEncoder() {
//可以自己定义密码匹配规则
@Override
public String encode(CharSequence rawPassword) {
return (String)rawPassword;//MD5Util.encode((String) rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
System.out.println(encodedPassword + "---" + (String)rawPassword);
return encodedPassword.equals((String) rawPassword);
}
})*/;
}
}
MvcConfig.java
视图解析器可以少写controller中的映射代码
package com.demo.config;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Component
/**
* 视图解析器
* @author TAO
*
*/
public class MvcConfig extends WebMvcConfigurerAdapter {
//直接页面跳转,不经过Controller,这样在没有任何处理业务的时候,快捷的页面转向定义会节省好多代码
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
//这里主要配置不需要任何认证就可以访问映射
registry.addViewController("/login").setViewName("login");
registry.addViewController("/").setViewName("login");
//registry.addViewController("/hello").setViewName("hello");
//registry.addViewController("/login").setViewName("login");
//registry.addViewController("/denied").setViewName("denied");
//registry.addViewController("/admin").setViewName("admin");
}
}
com.demo.controller
>HelloController.java
package com.demo.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/*
* 网络控制层:返回数据的controller。这里映射到resources目录下的templates的html页面。 *
*/
@Controller
public class HelloController {
//这里对比MvcConfig.java视图映射器,那里写了这里就可以少写这些代码
/*@RequestMapping("/")
public String index() {
return "home";
}
@RequestMapping("/home")
public String home() {
return "home";
}*/
/*当我们访问这个URL的时候,Spring Security会帮我们验证当前用户是否有权限访问该地址。
*官方推荐的鉴权注解方式,控制权限到请求方法级别。可通过三种方式的注解:
*注解方式1:@Secured, spring自带的注解方法:securedEnabled = true
*注解方式2:@PreAuthorize,方法调用前注解:securedEnabled = true
*注解方式2:@RolesAllowed,非spring框架: jsr250Enabled = true
*注意1:角色要填全名!
*注意2:一定要在自定义的WebSecurityConfigurerAdapter中添加注解。@EnableGlobalMethodSecurity(axx=bxx)!axx/bxx见上
*/
@Secured("ROLE_USER")
@RequestMapping("/hello")
//@PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
public String hello(){
return "hello";
}
@RequestMapping(value = "/login")
public String login() {
return "login";
}
@RequestMapping(value = "/logout")
public String logout() {
return "home";
}
@RequestMapping(value = "/denied")
public String denied() {
return "denied";
}
@Secured("ROLE_ADMIN")
@RequestMapping(value = "/admin")
//@PreAuthorize("hasAnyRole('ROLE_ADMIN')")
public String admin() {
return "admin";
}
}
com.demo
>DemoApplication.java
程序入口
package com.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//这个表示mybatis自动扫描dao接口的包名,
@MapperScan("com.demo")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
*------------------------------------------java代码搞定开始静态界面-------------------------------------------------
login.html登入界面,hello.html欢迎页-用户权限页,denied.html-拒绝访问页,admin.html管理员页
*login.html
Spring Security Example
无效的用户名和密码。.
您已经注销了.
使用账号密码登录
hello.html
Hello World!
普通。每个人都可以参观。
这是管理员访问.
这是用户访问。
这是TAO才能访问
Click here 退出
Click here 去管理员页面
admin.html
Admin Page
管理员页
Click here 普通界面
Click here 退出
denied.html
拒绝访问
您的访问被拒绝
这是一个拒绝访问的页面
Click here 去你好页面
Click here 退出
login.html
有点简陋主要学习框架
这里直接/或者login都可以,其他映射路径全部拦截到login这里
登入成功后
用的是admin用户
图中的(这是用户访问。)
这里每个用户都有一个ROLE_USER这样的权限,解释一下:由于静态资源路径这样写/static/** 这样放不过,去所以自能写成/星星(这里/星星转义打不出理解一下你懂得)
然后所有请求都要配置一个@Secured(“ROLE_ADMIN”)这样的权限请求,(注意除/,和/login不然登入页面都看不到)
其实这里有三个权限提示但是这里只显示了两个,一个是任何用户都能看得到的红箭头标记了,上面解释了,另一个就是当前登入用户的权限(用的是admin用户 —就是管理员)
这个界面是权限拒接界面上面有提到denied.html
https://github.com/xjjxltzf/CSDN.git